From 5a35fbf5c1246df33cca365ab5feaaf3ed0e6887 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Tue, 26 Mar 2019 08:23:57 -0400 Subject: [PATCH] [Tests] add some tests --- .../enzyme-test-suite/test/Adapter-spec.jsx | 37 ++++++++- .../test/ReactWrapper-spec.jsx | 41 +++++++++- .../test/shared/methods/@@iterator.jsx | 3 +- .../test/shared/methods/context.jsx | 77 +++++++++++++++++++ .../test/shared/methods/renderProp.jsx | 37 ++++----- .../test/shared/methods/setContext.jsx | 11 +++ .../test/shared/methods/setProps.jsx | 21 +++++ 7 files changed, 199 insertions(+), 28 deletions(-) create mode 100644 packages/enzyme-test-suite/test/shared/methods/context.jsx diff --git a/packages/enzyme-test-suite/test/Adapter-spec.jsx b/packages/enzyme-test-suite/test/Adapter-spec.jsx index 5cd017c39..5845432ad 100644 --- a/packages/enzyme-test-suite/test/Adapter-spec.jsx +++ b/packages/enzyme-test-suite/test/Adapter-spec.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { expect } from 'chai'; import jsdom from 'jsdom'; import { get } from 'enzyme/build/configuration'; -import { configure, shallow } from 'enzyme'; +import { configure, shallow, EnzymeAdapter } from 'enzyme'; import inspect from 'object-inspect'; import { Portal, @@ -77,6 +77,41 @@ describe('Adapter', () => { }); }); + describe('base class', () => { + it('constructs', () => { + const instance = new EnzymeAdapter(); + expect(instance).to.have.property('options'); + expect(instance.options).to.be.an('object'); + }); + + it('throws on abstract methods', () => { + expect(() => new EnzymeAdapter().createRenderer()).to.throw( + Error, + 'createRenderer is a required method of EnzymeAdapter, but was not implemented.', + ); + expect(() => new EnzymeAdapter().nodeToElement()).to.throw( + Error, + 'nodeToElement is a required method of EnzymeAdapter, but was not implemented.', + ); + expect(() => new EnzymeAdapter().isValidElement()).to.throw( + Error, + 'isValidElement is a required method of EnzymeAdapter, but was not implemented.', + ); + expect(() => new EnzymeAdapter().createElement()).to.throw( + Error, + 'createElement is a required method of EnzymeAdapter, but was not implemented.', + ); + }); + + describe('invokeSetStateCallback', () => { + it('has the right length', () => { + expect(EnzymeAdapter.prototype).to.have.property('invokeSetStateCallback'); + expect(EnzymeAdapter.prototype.invokeSetStateCallback).to.be.a('function'); + expect(EnzymeAdapter.prototype.invokeSetStateCallback).to.have.lengthOf(2); + }); + }); + }); + describeWithDOM('mounted render', () => { function hydratedTreeMatchesUnhydrated(element, hydrate = false) { const markup = renderToString(element); diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index e7f2b25a1..2d607528b 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -45,6 +45,21 @@ describeWithDOM('mount', () => { }); describe('top level wrapper', () => { + wrap() + .withGlobal('document', () => null) + .withGlobal('window', () => null) + .it('throws without a global document and window', () => { + expect(() => mount(
)).to.throw( + Error, + 'It looks like you called `mount()` without a global document being loaded.', + ); + + expect(() => new ReactWrapper(
)).to.throw( + Error, + 'It looks like you called `mount()` without a global document being loaded.', + ); + }); + it('does what i expect', () => { class Box extends React.Component { render() { @@ -861,10 +876,29 @@ describeWithDOM('mount', () => { }); describe('.ref(refName)', () => { + class WithoutRef extends React.Component { + render() { return
; } + } + + class WithRef extends React.Component { + render() { return
; } + } + + class RendersWithRef extends React.Component { + render() { return ; } + } + + it('throws when called on not the root', () => { + const wrapper = mount(); + const found = wrapper.find(WithRef); + expect(found).to.have.lengthOf(1); + expect(() => found.ref('ref')).to.throw( + Error, + 'ReactWrapper::ref(refname) can only be called on the root', + ); + }); + it('unavailable ref should return undefined', () => { - class WithoutRef extends React.Component { - render() { return
; } - } const wrapper = mount(); const ref = wrapper.ref('not-a-ref'); @@ -872,7 +906,6 @@ describeWithDOM('mount', () => { }); it('gets a wrapper of the node matching the provided refName', () => { - class Foo extends React.Component { render() { return ( diff --git a/packages/enzyme-test-suite/test/shared/methods/@@iterator.jsx b/packages/enzyme-test-suite/test/shared/methods/@@iterator.jsx index 36fd276f5..94c31a1b0 100644 --- a/packages/enzyme-test-suite/test/shared/methods/@@iterator.jsx +++ b/packages/enzyme-test-suite/test/shared/methods/@@iterator.jsx @@ -27,7 +27,7 @@ export default function describeIterator({ } } const wrapper = Wrap(); - const [a, b, c, d] = wrapper.find('a'); + const [a, b, c, d, ...e] = wrapper.find('a'); const a1 = wrapper.find('a').get(0); const b1 = wrapper.find('a').get(1); const c1 = wrapper.find('a').get(2); @@ -36,6 +36,7 @@ export default function describeIterator({ expect(b1).to.deep.equal(b); expect(c1).to.deep.equal(c); expect(d1).to.deep.equal(d); + expect(e).to.eql([]); }); it('returns an iterable iterator', () => { diff --git a/packages/enzyme-test-suite/test/shared/methods/context.jsx b/packages/enzyme-test-suite/test/shared/methods/context.jsx new file mode 100644 index 000000000..055544962 --- /dev/null +++ b/packages/enzyme-test-suite/test/shared/methods/context.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { expect } from 'chai'; + +import { + itIf, +} from '../../_helpers'; +import { + is, +} from '../../_helpers/version'; + +import { + createClass, +} from '../../_helpers/react-compat'; + +export default function describeContext({ + Wrap, + WrapperName, +}) { + describe('.context()', () => { + const contextTypes = { + name: PropTypes.string, + }; + const SimpleComponent = createClass({ + contextTypes, + render() { + const { name } = this.context; + return
{name}
; + }, + }); + + function SimpleComponentSFC(props, { name }) { + return
{name}
; + } + SimpleComponentSFC.contextTypes = contextTypes; + + it('throws when not called on the root', () => { + const context = { name:
}; + const wrapper = Wrap(, { context }); + const main = wrapper.find('main'); + expect(main).to.have.lengthOf(1); + expect(() => main.context()).to.throw( + Error, + `${WrapperName}::context() can only be called on the root`, + ); + }); + + it('throws if it is called when wrapper didn’t include context', () => { + const wrapper = Wrap(); + expect(() => wrapper.context()).to.throw( + Error, + `${WrapperName}::context() can only be called on a wrapper that was originally passed a context option`, + ); + }); + + itIf(is('>= 16'), 'throws on SFCs that lack an instance', () => { + const context = { name: 'bob' }; + const wrapper = Wrap(, { context }); + expect(() => wrapper.context()).to.throw( + Error, + `${WrapperName}::context() can only be called on wrapped nodes that have a non-null instance`, + ); + }); + + it('works with no arguments', () => { + const context = { name: {} }; + const wrapper = Wrap(, { context }); + expect(wrapper.context()).to.eql(context); + }); + + it('works with a key name', () => { + const context = { name: {} }; + const wrapper = Wrap(, { context }); + expect(wrapper.context('name')).to.equal(context.name); + }); + }); +} diff --git a/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx b/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx index e93f4db1d..99db157a6 100644 --- a/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx +++ b/packages/enzyme-test-suite/test/shared/methods/renderProp.jsx @@ -17,19 +17,24 @@ export default function describeRenderProp({ wrap() .withConsoleThrows() .describe('.renderProp()', () => { - it('returns a wrapper around the node returned from the render prop', () => { - class Foo extends React.Component { - render() { - return
; - } + class Foo extends React.Component { + render() { + return
; } - class Bar extends React.Component { - render() { - const { render: r } = this.props; - return
{r()}
; - } + } + class Bar extends React.Component { + render() { + const { render: r } = this.props; + return
{r()}
; } + } + class RendersBar extends React.Component { + render() { + return ; + } + } + it('returns a wrapper around the node returned from the render prop', () => { const wrapperA = Wrap(
} />
); const renderPropWrapperA = wrapperA.find(Bar).renderProp('render')(); expect(renderPropWrapperA.find(Foo)).to.have.lengthOf(1); @@ -61,18 +66,6 @@ export default function describeRenderProp({ wrap() .withOverride(() => getAdapter(), 'wrap', () => undefined) .it('throws with a react adapter that lacks a `.wrap`', () => { - class Foo extends React.Component { - render() { - return
; - } - } - class Bar extends React.Component { - render() { - const { render: r } = this.props; - return
{r()}
; - } - } - const wrapper = Wrap(
} />
); expect(() => wrapper.find(Bar).renderProp('render')).to.throw(RangeError); }); diff --git a/packages/enzyme-test-suite/test/shared/methods/setContext.jsx b/packages/enzyme-test-suite/test/shared/methods/setContext.jsx index dd018cfca..2918f5960 100644 --- a/packages/enzyme-test-suite/test/shared/methods/setContext.jsx +++ b/packages/enzyme-test-suite/test/shared/methods/setContext.jsx @@ -44,6 +44,17 @@ export default function describeSetContext({ ); }); + it('throws when not called on the root', () => { + const context = { name:
}; + const wrapper = Wrap(, { context }); + const main = wrapper.find('main'); + expect(main).to.have.lengthOf(1); + expect(() => main.setContext()).to.throw( + Error, + `${WrapperName}::setContext() can only be called on the root`, + ); + }); + describeIf(is('> 0.13'), 'stateless functional components', () => { const SFC = (props, { name }) => (
{name}
diff --git a/packages/enzyme-test-suite/test/shared/methods/setProps.jsx b/packages/enzyme-test-suite/test/shared/methods/setProps.jsx index 52bf55895..9bde5ff0c 100644 --- a/packages/enzyme-test-suite/test/shared/methods/setProps.jsx +++ b/packages/enzyme-test-suite/test/shared/methods/setProps.jsx @@ -15,6 +15,7 @@ import { is } from '../../_helpers/version'; export default function describeSetProps({ Wrap, + WrapperName, isShallow, }) { describe('.setProps(newProps[, callback)', () => { @@ -43,6 +44,16 @@ export default function describeSetProps({ ); } + class RendersFoo extends React.Component { + render() { + return ( +
+ +
+ ); + } + } + it('throws on a non-function callback', () => { const wrapper = Wrap(); @@ -54,6 +65,16 @@ export default function describeSetProps({ expect(() => wrapper.setProps({}, {})).to.throw(); }); + it('throws when not called on the root', () => { + const wrapper = Wrap(); + const child = wrapper.find(Foo); + expect(child).to.have.lengthOf(1); + expect(() => child.setProps({})).to.throw( + Error, + `${WrapperName}::setProps() can only be called on the root`, + ); + }); + it('sets props for a component multiple times', () => { const wrapper = Wrap(); expect(wrapper.find('.foo')).to.have.lengthOf(1);