;
+ }
+
+ @connect(
+ state => ({string: state}),
+ dispatch => ({ dispatch })
+ )
class Container extends Component {
render() {
- return
;
+ return render(this.props);
}
}
- expect(Container.displayName).toBe('Connector(Container)');
+ const tree = TestUtils.renderIntoDocument(
+
+ {() => (
+
+ )}
+
+ );
+
+ const div = TestUtils.findRenderedDOMComponentWithTag(tree, 'div');
+ expect(spy.calls.length).toBe(1);
+ expect(div.props.string).toBe('');
+ store.dispatch({ type: 'APPEND', body: 'a'});
+ expect(spy.calls.length).toBe(2);
+ store.dispatch({ type: 'APPEND', body: 'b'});
+ expect(spy.calls.length).toBe(3);
+ store.dispatch({ type: 'APPEND', body: ''});
+ expect(spy.calls.length).toBe(3);
+ });
+
+ it('should throw an error if mapState, mapDispatch, or mergeProps returns anything but a plain object', () => {
+ const store = createStore(() => ({}));
+
+ function makeContainer(mapState, mapDispatch, mergeProps) {
+ return React.createElement(
+ @connect(mapState, mapDispatch, mergeProps)
+ class Container extends Component {
+ render() {
+ return
;
+ }
+ }
+ );
+ }
+
+ function AwesomeMap() { }
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => 1, () => ({}), () => ({})) }
+
+ );
+ }).toThrow(/mapState/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => 'hey', () => ({}), () => ({})) }
+
+ );
+ }).toThrow(/mapState/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => new AwesomeMap(), () => ({}), () => ({})) }
+
+ );
+ }).toThrow(/mapState/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => ({}), () => 1, () => ({})) }
+
+ );
+ }).toThrow(/mapDispatch/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => ({}), () => 'hey', () => ({})) }
+
+ );
+ }).toThrow(/mapDispatch/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => ({}), () => new AwesomeMap(), () => ({})) }
+
+ );
+ }).toThrow(/mapDispatch/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => ({}), () => ({}), () => 1) }
+
+ );
+ }).toThrow(/mergeProps/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => ({}), () => ({}), () => 'hey') }
+
+ );
+ }).toThrow(/mergeProps/);
+
+ expect(() => {
+ TestUtils.renderIntoDocument(
+
+ { () => makeContainer(() => ({}), () => ({}), () => new AwesomeMap()) }
+
+ );
+ }).toThrow(/mergeProps/);
+ });
+
+ it('should set the displayName correctly', () => {
+ expect(connect(state => state)(
+ class Foo extends Component {
+ render() {
+ return
;
+ }
+ }
+ ).displayName).toBe('Connect(Foo)');
+
+ expect(connect(state => state)(
+ createClass({
+ displayName: 'Bar',
+ render() {
+ return
;
+ }
+ })
+ ).displayName).toBe('Connect(Bar)');
+
+ expect(connect(state => state)(
+ createClass({
+ render() {
+ return
;
+ }
+ })
+ ).displayName).toBe('Connect(Component)');
});
it('should expose the wrapped component as DecoratedComponent', () => {
@@ -154,5 +474,39 @@ describe('React', () => {
expect(decorated.DecoratedComponent).toBe(Container);
});
+
+ it('should return the instance of the wrapped component for use in calling child methods', () => {
+ const store = createStore(() => ({}));
+
+ const someData = {
+ some: 'data'
+ };
+
+ class Container extends Component {
+ someInstanceMethod() {
+ return someData;
+ }
+
+ render() {
+ return
;
+ }
+ }
+
+ const decorator = connect(state => state);
+ const Decorated = decorator(Container);
+
+ const tree = TestUtils.renderIntoDocument(
+
+ {() => (
+
+ )}
+
+ );
+
+ const decorated = TestUtils.findRenderedComponentWithType(tree, Decorated);
+
+ expect(() => decorated.someInstanceMethod()).toThrow();
+ expect(decorated.getUnderlyingRef().someInstanceMethod()).toBe(someData);
+ });
});
});
diff --git a/test/utils/getDisplayName.spec.js b/test/utils/getDisplayName.spec.js
deleted file mode 100644
index 6a1740d76..000000000
--- a/test/utils/getDisplayName.spec.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import expect from 'expect';
-import { createClass, Component } from 'react';
-import getDisplayName from '../../src/utils/getDisplayName';
-
-describe('Utils', () => {
- describe('getDisplayName', () => {
- it('should extract the component class name', () => {
- const names = [
- createClass({ displayName: 'Foo', render() {} }),
- class Bar extends Component {},
- createClass({ render() {} })
- ].map(getDisplayName);
-
- expect(names).toEqual(['Foo', 'Bar', 'Component']);
- });
- });
-});
diff --git a/test/utils/wrapActionCreators.js b/test/utils/wrapActionCreators.js
new file mode 100644
index 000000000..af31ce4d6
--- /dev/null
+++ b/test/utils/wrapActionCreators.js
@@ -0,0 +1,31 @@
+import expect from 'expect';
+import wrapActionCreators from '../../src/utils/wrapActionCreators';
+
+describe('Utils', () => {
+ describe('wrapActionCreators', () => {
+ it('should return a function that wraps argument in a call to bindActionCreators', () => {
+
+ function dispatch(action) {
+ return {
+ dispatched: action
+ };
+ }
+
+ const actionResult = {an: 'action'};
+
+ const actionCreators = {
+ action: () => actionResult
+ };
+
+ const wrapped = wrapActionCreators(actionCreators);
+ expect(wrapped).toBeA(Function);
+ expect(() => wrapped(dispatch)).toNotThrow();
+ expect(() => wrapped().action()).toThrow();
+
+ const bound = wrapped(dispatch);
+ expect(bound.action).toNotThrow();
+ expect(bound.action().dispatched).toBe(actionResult);
+
+ });
+ });
+});