diff --git a/test/ShallowWrapper-spec.js b/test/ShallowWrapper-spec.js index ba55df94a..4926bbf34 100644 --- a/test/ShallowWrapper-spec.js +++ b/test/ShallowWrapper-spec.js @@ -2,7 +2,7 @@ import React from 'react'; import { expect } from 'chai'; import { shallow, render, ShallowWrapper } from '../src/'; import sinon from 'sinon'; -import { describeIf } from './_helpers'; +import { describeIf, itIf } from './_helpers'; import { REACT013 } from '../src/version'; describe('shallow', () => { @@ -49,9 +49,42 @@ describe('shallow', () => { expect(wrapper.context().name).to.equal(context.name); expect(wrapper.context('name')).to.equal(context.name); }); + + describeIf(!REACT013, 'stateless function components', () => { + it('can pass in context', () => { + const SimpleComponent = (props, context) => ( +
{context.name}
+ ); + SimpleComponent.contextTypes = { name: React.PropTypes.string }; + + const wrapper = shallow(, { context }); + expect(wrapper.text()).to.equal('foo'); + }); + + it('should not throw if context is passed in but contextTypes is missing', () => { + const SimpleComponent = (props, context) => ( +
{context.name}
+ ); + + const wrapper = shallow(, { context }); + expect(() => shallow(, { context })).to.not.throw(Error); + }); + + it('is instrospectable through context API', () => { + const SimpleComponent = (props, context) => ( +
{context.name}
+ ); + SimpleComponent.contextTypes = { name: React.PropTypes.string }; + + const wrapper = shallow(, { context }); + + expect(wrapper.context().name).to.equal(context.name); + expect(wrapper.context('name')).to.equal(context.name); + }); + }); }); - describeIf(!REACT013, 'stateless components', () => { + describeIf(!REACT013, 'stateless function components', () => { it('works with stateless components', () => { const Foo = ({ foo }) => (
@@ -158,6 +191,21 @@ describe('shallow', () => { expect(wrapper.contains(passes2)).to.equal(true); }); + describeIf(!REACT013, 'stateless function components', () => { + it('should match composite components', () => { + const Foo = () => ( +
+ ); + + const wrapper = shallow( +
+ +
+ ); + const b = ; + expect(wrapper.contains(b)).to.equal(true); + }); + }); }); describe('.equals(node)', () => { @@ -206,6 +254,35 @@ describe('shallow', () => { expect(shallow().equals()).to.equal(false); }); + describeIf(!REACT013, 'stateless components', () => { + it('should match composite stateless components', () => { + const Foo = () => ( +
+ ); + + const wrapper = shallow( +
+ +
+ ); + const b =
; + expect(wrapper.equals(b)).to.equal(true); + }); + + it('should not expand `node` content', () => { + const Bar = () => ( +
+ ); + + const Foo = () => ( + + ); + + expect(shallow().equals()).to.equal(true); + expect(shallow().equals()).to.equal(false); + }); + }); + }); describe('.find(selector)', () => { @@ -258,7 +335,6 @@ describe('shallow', () => { expect(wrapper.find('Foo').type()).to.equal(Foo); }); - it('should find multiple elements based on a class name', () => { const wrapper = shallow(
@@ -442,6 +518,32 @@ describe('shallow', () => { expect(() => wrapper.find([])).to.throw(Error); expect(() => wrapper.find(null)).to.throw(Error); }); + + describeIf(!REACT013, 'stateless function components', () => { + it('should find a component based on a constructor', () => { + const Foo = () => ( +
+ ); + const wrapper = shallow( +
+ +
+ ); + expect(wrapper.find(Foo).type()).to.equal(Foo); + }); + + it('should find a component based on a display name', () => { + const Foo = () => ( +
+ ); + const wrapper = shallow( +
+ +
+ ); + expect(wrapper.find('Foo').type()).to.equal(Foo); + }); + }); }); describe('.findWhere(predicate)', () => { @@ -489,7 +591,7 @@ describe('shallow', () => { expect(spy.args[3][0].hasClass('bux')).to.equal(true); }); - describeIf(!REACT013, 'stateless functional components', () => { + describeIf(!REACT013, 'stateless function components', () => { it('finds nodes', () => { const SFC = function SFC({ selector }) { return ( @@ -634,6 +736,50 @@ describe('shallow', () => { wrapper.setProps({ x: 5 }); // Just force a re-render expect(wrapper.first('div').text()).to.equal('yolo'); }); + + describeIf(!REACT013, 'stateless function components', () => { + it('should set props for a component multiple times', () => { + const Foo = (props) => ( +
+ {props.id} +
+ ); + + const wrapper = shallow(); + expect(wrapper.find('.foo').length).to.equal(1); + wrapper.setProps({ id: 'bar', foo: 'bla' }); + expect(wrapper.find('.bar').length).to.equal(1); + }); + + it('should merge newProps with oldProps', () => { + const Foo = (props) => ( +
+ ); + + const wrapper = shallow(); + expect(wrapper.props().a).to.equal('a'); + expect(wrapper.props().b).to.equal('b'); + + wrapper.setProps({ b: 'c', d: 'e' }); + expect(wrapper.props().a).to.equal('a'); + expect(wrapper.props().b).to.equal('c'); + expect(wrapper.props().d).to.equal('e'); + }); + + it('should pass in old context', () => { + const Foo = (props, context) => ( +
{context.x}
+ ); + Foo.contextTypes = { x: React.PropTypes.string }; + + const context = { x: 'yolo' }; + const wrapper = shallow(, { context }); + expect(wrapper.first('div').text()).to.equal('yolo'); + + wrapper.setProps({ x: 5 }); // Just force a re-render + expect(wrapper.first('div').text()).to.equal('yolo'); + }); + }); }); describe('.setContext(newContext)', () => { @@ -660,6 +806,28 @@ describe('shallow', () => { const wrapper = shallow(); expect(() => wrapper.setContext({ name: 'bar' })).to.throw(Error); }); + + describeIf(!REACT013, 'stateless function components', () => { + const SimpleComponent = (props, context) => ( +
{context.name}
+ ); + SimpleComponent.contextTypes = { name: React.PropTypes.string }; + + it('should set context for a component multiple times', () => { + const context = { name: 'foo' }; + const wrapper = shallow(, { context }); + expect(wrapper.text()).to.equal('foo'); + wrapper.setContext({ name: 'bar' }); + expect(wrapper.text()).to.equal('bar'); + wrapper.setContext({ name: 'baz' }); + expect(wrapper.text()).to.equal('baz'); + }); + + it('should throw if it is called when shallow didnt include context', () => { + const wrapper = shallow(); + expect(() => wrapper.setContext({ name: 'bar' })).to.throw(Error); + }); + }); }); describe('.simulate(eventName, data)', () => { @@ -715,6 +883,37 @@ describe('shallow', () => { expect(spy.args[0][1]).to.equal(b); }); + describeIf(!REACT013, 'stateless function components', () => { + it('should simulate events', () => { + const spy = sinon.spy(); + const Foo = (props) => ( + foo + ); + + const wrapper = shallow(); + + expect(spy.calledOnce).to.equal(false); + wrapper.find('a').simulate('click'); + expect(spy.calledOnce).to.equal(true); + }); + + + it('should pass in event data', () => { + const spy = sinon.spy(); + const Foo = (props) => ( + foo + ); + + const wrapper = shallow(); + const a = {}; + const b = {}; + + wrapper.simulate('click', a, b); + expect(spy.args[0][0]).to.equal(a); + expect(spy.args[0][1]).to.equal(b); + }); + }); + describe('Normalizing JS event names', () => { it('should convert lowercase events to React camelcase', () => { const spy = sinon.spy(); @@ -748,6 +947,18 @@ describe('shallow', () => { wrapper.simulate('mouseenter'); expect(spy.calledOnce).to.equal(true); }); + + it('should convert lowercase events to React camelcase in stateless components', () => { + const spy = sinon.spy(); + const Foo = () => ( + foo + ); + + const wrapper = shallow(); + + wrapper.simulate('mouseenter'); + expect(spy.calledOnce).to.equal(true); + }); }); }); @@ -940,6 +1151,40 @@ describe('shallow', () => { matchesRender(
>
); }); + describeIf(!REACT013, 'stateless function components', () => { + it('should handle nodes with mapped children', () => { + const Foo = (props) => ( +
+ {props.items.map(x => x)} +
+ ); + matchesRender(); + matchesRender( + abc, + def, + hij, + ]} + /> + ); + }); + + it('should render composite components dumbly', () => { + const Foo = () => ( +
+ ); + + const wrapper = shallow( +
+ +
test
+
+ ); + expect(wrapper.text()).to.equal('test'); + }); + }); + }); describe('.props()', () => { @@ -1110,6 +1355,31 @@ describe('shallow', () => { expect(children.at(0).hasClass('bar')).to.equal(true); expect(children.at(1).hasClass('baz')).to.equal(true); }); + + describeIf(!REACT013, 'stateless function components', () => { + it('should handle mixed children with and without arrays', () => { + const Foo = (props) => ( +
+ + {props.items.map(x => x)} +
+ ); + + const wrapper = shallow( + abc, + def, + ]} + /> + ); + expect(wrapper.children().length).to.equal(3); + expect(wrapper.children().at(0).hasClass('foo')).to.equal(true); + expect(wrapper.children().at(1).hasClass('bar')).to.equal(true); + expect(wrapper.children().at(2).hasClass('baz')).to.equal(true); + }); + }); + }); describe('.childAt(index)', () => { @@ -1556,6 +1826,26 @@ describe('shallow', () => { expect(wrapper.find(Bar).shallow().find('.in-bar')).to.have.length(1); }); + describeIf(!REACT013, 'stateless function components', () => { + it('should return a shallow rendered instance of the current node', () => { + const Bar = () => ( +
+
+
+ ); + const Foo = () => ( +
+ +
+ ); + + const wrapper = shallow(); + expect(wrapper.find('.in-bar')).to.have.length(0); + expect(wrapper.find(Bar)).to.have.length(1); + expect(wrapper.find(Bar).shallow().find('.in-bar')).to.have.length(1); + }); + }); + }); describe('.first()', () => { @@ -1672,6 +1962,27 @@ describe('shallow', () => { ); }); + describeIf(!REACT013, 'stateless function components', () => { + it('should render out nested composite components', () => { + const Foo = () => ( +
+ ); + const Bar = () => ( +
+ +
+ ); + + const wrapper = shallow(); + expect(wrapper.html()).to.equal( + `
` + ); + expect(wrapper.find(Foo).html()).to.equal( + `
` + ); + }); + }); + }); describe('.unmount()', () => { @@ -1722,9 +2033,28 @@ describe('shallow', () => { expect(renderedFoo.find('.in-bar')).to.have.length(0); }); + describeIf(!REACT013, 'stateless function components', () => { + it('should return a cheerio wrapper around the current node', () => { + const Foo = () => ( +
+ ); + const Bar = () => ( +
+ +
+ ); + + const wrapper = shallow(); + expect(wrapper.render().find('.in-bar')).to.have.length(1); + const renderedFoo = wrapper.find(Foo).render(); + expect(renderedFoo.find('.in-foo')).to.have.length(1); + expect(renderedFoo.find('.in-bar')).to.have.length(0); + }); + }); + }); - it('works with components that return null', () => { + it('works with class components that return null', () => { class Foo extends React.Component { render() { return null;