UNPKG

redux-form

Version:

A higher order component decorator for forms using Redux and React

1,533 lines (1,281 loc) 64.4 kB
'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _expect = require('expect'); var _expect2 = _interopRequireDefault(_expect); var _expectElement = require('expect-element'); var _expectElement2 = _interopRequireDefault(_expectElement); var _reactRedux = require('react-redux'); var _redux = require('redux'); var _reduxImmutablejs = require('redux-immutablejs'); var _reactAddonsTestUtils = require('react-addons-test-utils'); var _reactAddonsTestUtils2 = _interopRequireDefault(_reactAddonsTestUtils); var _reduxForm = require('../reduxForm'); var _reduxForm2 = _interopRequireDefault(_reduxForm); var _reducer = require('../reducer'); var _reducer2 = _interopRequireDefault(_reducer); var _FieldArray = require('../FieldArray'); var _FieldArray2 = _interopRequireDefault(_FieldArray); var _Field = require('../Field'); var _Field2 = _interopRequireDefault(_Field); var _Fields = require('../Fields'); var _Fields2 = _interopRequireDefault(_Fields); var _plain = require('../structure/plain'); var _plain2 = _interopRequireDefault(_plain); var _expectations = require('../structure/plain/expectations'); var _expectations2 = _interopRequireDefault(_expectations); var _immutable = require('../structure/immutable'); var _immutable2 = _interopRequireDefault(_immutable); var _expectations3 = require('../structure/immutable/expectations'); var _expectations4 = _interopRequireDefault(_expectations3); var _addExpectations = require('./addExpectations'); var _addExpectations2 = _interopRequireDefault(_addExpectations); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* eslint react/no-multi-comp:0 */ _expect2.default.extend(_expectElement2.default); var describeFieldArray = function describeFieldArray(name, structure, combineReducers, expect) { var reduxForm = (0, _reduxForm2.default)(structure); var FieldArray = (0, _FieldArray2.default)(structure); var Field = (0, _Field2.default)(structure); var Fields = (0, _Fields2.default)(structure); var reducer = (0, _reducer2.default)(structure); var fromJS = structure.fromJS; var getIn = structure.getIn; var size = structure.size; var makeStore = function makeStore(initial) { return (0, _redux.createStore)(combineReducers({ form: reducer }), fromJS({ form: initial })); }; var TestComponent = function (_Component) { _inherits(TestComponent, _Component); function TestComponent() { _classCallCheck(this, TestComponent); return _possibleConstructorReturn(this, (TestComponent.__proto__ || Object.getPrototypeOf(TestComponent)).apply(this, arguments)); } _createClass(TestComponent, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, 'TEST INPUT' ); } }]); return TestComponent; }(_react.Component); var testProps = function testProps(state) { var config = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; var store = makeStore({ testForm: state }); var Form = function (_Component2) { _inherits(Form, _Component2); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm(_extends({ form: 'testForm' }, config))(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); return _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, TestComponent).props; }; describe(name, function () { it('should throw an error if not in ReduxForm', function () { expect(function () { _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) )); }).toThrow(/must be inside a component decorated with reduxForm/); }); it('should get length from Redux state', function () { var props = testProps({ values: { foo: ['a', 'b', 'c'] } }); expect(props.fields.length).toBe(3); }); it('should be okay with no array value', function () { var iterate = (0, _expect.createSpy)(); var props = testProps({ values: {} }); expect(props.fields.length).toBe(0); props.fields.forEach(iterate); props.fields.map(iterate); expect(iterate).toNotHaveBeenCalled(); }); it('should get dirty/pristine from Redux state', function () { var props1 = testProps({ initial: { foo: ['a', 'b', 'c'] }, values: { foo: ['a', 'b', 'c'] } }); expect(props1.meta.pristine).toBe(true); expect(props1.meta.dirty).toBe(false); var props2 = testProps({ initial: { foo: ['a', 'b', 'c'] }, values: { foo: ['a', 'b'] } }); expect(props2.meta.pristine).toBe(false); expect(props2.meta.dirty).toBe(true); }); it('should get touched from Redux state', function () { var props1 = testProps({ values: { foo: 'bar' } }); expect(props1.meta.touched).toBe(false); var props2 = testProps({ values: { foo: 'bar' }, fields: { foo: { touched: true } } }); expect(props2.meta.touched).toBe(true); }); it('should provide forEach', function () { var props = testProps({ values: { foo: ['a', 'b', 'c'] } }); expect(props.fields.forEach).toBeA('function'); var iterate = (0, _expect.createSpy)(); props.fields.forEach(iterate); expect(iterate).toHaveBeenCalled(); expect(iterate.calls.length).toBe(3); expect(iterate.calls[0].arguments).toEqual(['foo[0]', 0]); expect(iterate.calls[1].arguments).toEqual(['foo[1]', 1]); expect(iterate.calls[2].arguments).toEqual(['foo[2]', 2]); }); it('should provide map', function () { var props = testProps({ values: { foo: ['a', 'b', 'c'] } }); expect(props.fields.map).toBeA('function'); var iterate = (0, _expect.createSpy)(); props.fields.map(iterate); expect(iterate).toHaveBeenCalled(); expect(iterate.calls.length).toBe(3); expect(iterate.calls[0].arguments).toEqual(['foo[0]', 0]); expect(iterate.calls[1].arguments).toEqual(['foo[1]', 1]); expect(iterate.calls[2].arguments).toEqual(['foo[2]', 2]); }); it('should provide insert', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.insert).toBeA('function'); }); it('should provide push', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.push).toBeA('function'); }); it('should provide pop', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.pop).toBeA('function'); }); it('should provide shift', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.shift).toBeA('function'); }); it('should provide unshift', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.unshift).toBeA('function'); }); it('should provide move', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.move).toBeA('function'); }); it('should provide remove', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.remove).toBeA('function'); }); it('should provide removeAll', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.removeAll).toBeA('function'); }); it('should provide swap', function () { var props = testProps({ values: { foo: [] } }); expect(props.fields.swap).toBeA('function'); }); it('should provide pass through other props', function () { var store = makeStore({ testForm: { values: { foo: ['bar'] } } }); var renderArray = (0, _expect.createSpy)(function () { return _react2.default.createElement('div', null); }).andCallThrough(); var Form = function (_Component3) { _inherits(Form, _Component3); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: renderArray, otherProp: 'dog', anotherProp: 'cat' }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); expect(renderArray).toHaveBeenCalled(); expect(renderArray.calls.length).toBe(1); expect(renderArray.calls[0].arguments[0].fields.length).toBe(1); expect(renderArray.calls[0].arguments[0].otherProp).toBe('dog'); expect(renderArray.calls[0].arguments[0].anotherProp).toBe('cat'); }); it('should provide access to rendered component', function () { var store = makeStore({ testForm: { values: { foo: ['bar'] } } }); var TestComponent = function (_Component4) { _inherits(TestComponent, _Component4); function TestComponent() { _classCallCheck(this, TestComponent); return _possibleConstructorReturn(this, (TestComponent.__proto__ || Object.getPrototypeOf(TestComponent)).apply(this, arguments)); } _createClass(TestComponent, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, 'TEST INPUT' ); } }]); return TestComponent; }(_react.Component); var Form = function (_Component5) { _inherits(Form, _Component5); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent, withRef: true }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var field = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, FieldArray); var component = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, TestComponent); expect(field.getRenderedComponent()).toBe(component); }); it('should use initialValues', function () { var props = testProps({}, { initialValues: { foo: ['a', 'b', 'c'] } }); expect(props.fields.length).toBe(3); var iterate = (0, _expect.createSpy)(); props.fields.forEach(iterate); expect(iterate).toHaveBeenCalled(); expect(iterate.calls.length).toBe(3); expect(iterate.calls[0].arguments[0]).toBe('foo[0]'); expect(iterate.calls[1].arguments[0]).toBe('foo[1]'); expect(iterate.calls[2].arguments[0]).toBe('foo[2]'); }); it('should get sync errors from outer reduxForm component', function () { var props = testProps({ values: { foo: 'bar' } }, { validate: function validate() { return { foo: { _error: 'foo error' } }; } }); expect(props.meta.error).toBe('foo error'); }); it('should get async errors from Redux state', function () { var props = testProps({ values: { foo: 'bar' }, asyncErrors: { foo: { _error: 'foo error' } } }); expect(props.meta.error).toBe('foo error'); }); it('should get submit errors from Redux state', function () { var props = testProps({ values: { foo: 'bar' }, submitErrors: { foo: { _error: 'foo error' } } }); expect(props.meta.error).toBe('foo error'); }); it('should provide name getter', function () { var store = makeStore({ testForm: { values: { foo: ['bar'] } } }); var Form = function (_Component6) { _inherits(Form, _Component6); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var stub = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, FieldArray); expect(stub.name).toEqual('foo'); }); it('should provide value getter', function () { var store = makeStore({ testForm: { values: { foo: ['bar'] } } }); var Form = function (_Component7) { _inherits(Form, _Component7); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var stub = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, FieldArray); expect(stub.value).toEqualMap(['bar']); }); it('should provide dirty getter that is true when dirty', function () { var store = makeStore({ testForm: { initial: { foo: ['dog'] }, values: { foo: ['cat'] } } }); var Form = function (_Component8) { _inherits(Form, _Component8); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var stub = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, FieldArray); expect(stub.dirty).toBe(true); }); it('should provide dirty getter that is false when pristine', function () { var store = makeStore({ testForm: { initial: { foo: ['dog'] }, values: { foo: ['dog'] } } }); var Form = function (_Component9) { _inherits(Form, _Component9); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var stub = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, FieldArray); expect(stub.dirty).toBe(false); }); it('should provide pristine getter that is true when pristine', function () { var store = makeStore({ testForm: { initial: { foo: ['dog'] }, values: { foo: ['dog'] } } }); var Form = function (_Component10) { _inherits(Form, _Component10); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var stub = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, FieldArray); expect(stub.pristine).toBe(true); }); it('should provide pristine getter that is false when dirty', function () { var store = makeStore({ testForm: { initial: { foo: ['dog'] }, values: { foo: ['cat'] } } }); var Form = function (_Component11) { _inherits(Form, _Component11); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: TestComponent }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var stub = _reactAddonsTestUtils2.default.findRenderedComponentWithType(dom, FieldArray); expect(stub.pristine).toBe(false); }); it('should provide sync error for array field', function () { var store = makeStore({ testForm: { values: { foo: [{ library: 'redux-form', author: 'erikras' }] } } }); var validate = function validate() { return { foo: [{ _error: 'Too awesome!' }] }; }; var renderArray = function renderArray(_ref) { var fields = _ref.fields; return _react2.default.createElement( 'div', null, fields.map(function (name, index) { return _react2.default.createElement( 'div', { key: index }, _react2.default.createElement(Field, { name: name + '.library', component: 'input' }), _react2.default.createElement(Field, { name: name + '.author', component: 'input' }), _react2.default.createElement(Field, { name: name, component: function component(props) { return _react2.default.createElement( 'strong', null, props.meta.error ); } }) ); }) ); }; var Form = function (_Component12) { _inherits(Form, _Component12); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', component: renderArray }) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm', validate: validate })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var error = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithTag(dom, 'strong'); (0, _expect2.default)(error).toExist().toHaveText('Too awesome!'); }); it('should reconnect when name changes', function () { var store = makeStore({ testForm: { values: { foo: ['a', 'b'], bar: ['c'] } } }); var component = (0, _expect.createSpy)(function () { return _react2.default.createElement('div', null); }).andCallThrough(); var Form = function (_Component13) { _inherits(Form, _Component13); function Form() { _classCallCheck(this, Form); var _this13 = _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).call(this)); _this13.state = { field: 'foo' }; return _this13; } _createClass(Form, [{ key: 'render', value: function render() { var _this14 = this; return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: this.state.field, component: component }), _react2.default.createElement( 'button', { onClick: function onClick() { return _this14.setState({ field: 'bar' }); } }, 'Change' ) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); expect(component).toHaveBeenCalled(); expect(component.calls.length).toBe(1); expect(component.calls[0].arguments[0].fields.length).toBe(2); var button = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithTag(dom, 'button'); _reactAddonsTestUtils2.default.Simulate.click(button); expect(component.calls.length).toBe(2); expect(component.calls[1].arguments[0].fields.length).toBe(1); }); it('should reconnect when props change', function () { var store = makeStore(); var component = (0, _expect.createSpy)(function () { return _react2.default.createElement('div', null); }).andCallThrough(); var Form = function (_Component14) { _inherits(Form, _Component14); function Form() { _classCallCheck(this, Form); var _this15 = _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).call(this)); _this15.state = { foo: 'foo', bar: 'bar' }; return _this15; } _createClass(Form, [{ key: 'render', value: function render() { var _this16 = this; return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', foo: this.state.foo, bar: this.state.bar, component: component }), _react2.default.createElement( 'button', { onClick: function onClick() { return _this16.setState({ foo: 'qux', bar: 'baz' }); } }, 'Change' ) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); expect(component).toHaveBeenCalled(); expect(component.calls.length).toBe(1); expect(component.calls[0].arguments[0].foo).toBe('foo'); expect(component.calls[0].arguments[0].bar).toBe('bar'); var button = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithTag(dom, 'button'); _reactAddonsTestUtils2.default.Simulate.click(button); expect(component.calls.length).toBe(2); expect(component.calls[1].arguments[0].foo).toBe('qux'); expect(component.calls[1].arguments[0].bar).toBe('baz'); }); it('should allow addition after focus', function () { var store = makeStore(); var component = (0, _expect.createSpy)(function () { return _react2.default.createElement('div', null); }).andCallThrough(); var Form = function (_Component15) { _inherits(Form, _Component15); function Form() { _classCallCheck(this, Form); var _this17 = _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).call(this)); _this17.state = { foo: 'foo', bar: 'bar' }; return _this17; } _createClass(Form, [{ key: 'render', value: function render() { var _this18 = this; return _react2.default.createElement( 'div', null, _react2.default.createElement(FieldArray, { name: 'foo', foo: this.state.foo, bar: this.state.bar, component: component }), _react2.default.createElement( 'button', { onClick: function onClick() { return _this18.setState({ foo: 'qux', bar: 'baz' }); } }, 'Change' ) ); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); expect(component).toHaveBeenCalled(); expect(component.calls.length).toBe(1); expect(component.calls[0].arguments[0].foo).toBe('foo'); expect(component.calls[0].arguments[0].bar).toBe('bar'); var button = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithTag(dom, 'button'); _reactAddonsTestUtils2.default.Simulate.click(button); expect(component.calls.length).toBe(2); expect(component.calls[1].arguments[0].foo).toBe('qux'); expect(component.calls[1].arguments[0].bar).toBe('baz'); }); it('should rerender when items added or removed', function () { var store = makeStore({}); var renderField = (0, _expect.createSpy)(function (props) { return _react2.default.createElement('input', props.input); }).andCallThrough(); var renderFieldArray = (0, _expect.createSpy)(function (_ref2) { var fields = _ref2.fields; return _react2.default.createElement( 'div', null, fields.map(function (field) { return _react2.default.createElement(Field, { name: field, component: renderField, key: field }); }), _react2.default.createElement( 'button', { className: 'add', onClick: function onClick() { return fields.push(); } }, 'Add Dog' ), _react2.default.createElement( 'button', { className: 'remove', onClick: function onClick() { return fields.pop(); } }, 'Remove Dog' ) ); }).andCallThrough(); var Form = function (_Component16) { _inherits(Form, _Component16); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement(FieldArray, { name: 'dogs', component: renderFieldArray }); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var addButton = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithClass(dom, 'add'); var removeButton = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithClass(dom, 'remove'); // length is 0 expect(renderFieldArray).toHaveBeenCalled(); expect(renderFieldArray.calls.length).toBe(1); expect(renderFieldArray.calls[0].arguments[0].fields.length).toBe(0); // add field _reactAddonsTestUtils2.default.Simulate.click(addButton); // field array rerendered, length is 1 expect(renderFieldArray.calls.length).toBe(2); expect(renderFieldArray.calls[1].arguments[0].fields.length).toBe(1); // add field _reactAddonsTestUtils2.default.Simulate.click(addButton); // field array rerendered, length is 2 expect(renderFieldArray.calls.length).toBe(3); expect(renderFieldArray.calls[2].arguments[0].fields.length).toBe(2); // add field _reactAddonsTestUtils2.default.Simulate.click(addButton); // field array rerendered, length is 3 expect(renderFieldArray.calls.length).toBe(4); expect(renderFieldArray.calls[3].arguments[0].fields.length).toBe(3); // remove field _reactAddonsTestUtils2.default.Simulate.click(removeButton); // field array rerendered, length is 2 expect(renderFieldArray.calls.length).toBe(5); expect(renderFieldArray.calls[4].arguments[0].fields.length).toBe(2); // add field _reactAddonsTestUtils2.default.Simulate.click(addButton); // field array rerendered, length is 3 expect(renderFieldArray.calls.length).toBe(6); expect(renderFieldArray.calls[5].arguments[0].fields.length).toBe(3); }); it('should rerender when array sync error appears or disappears', function () { var store = makeStore({ testForm: { values: { dogs: [] } } }); var renderFieldArray = (0, _expect.createSpy)(function (_ref3) { var fields = _ref3.fields; return _react2.default.createElement( 'div', null, fields.map(function (field, index) { return _react2.default.createElement( 'div', { key: index }, field ); }), _react2.default.createElement( 'button', { className: 'add', onClick: function onClick() { return fields.push(); } }, 'Add Dog' ), _react2.default.createElement( 'button', { className: 'remove', onClick: function onClick() { return fields.pop(); } }, 'Remove Dog' ) ); }).andCallThrough(); var Form = function (_Component17) { _inherits(Form, _Component17); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement(FieldArray, { name: 'dogs', component: renderFieldArray }); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm', validate: function validate(values) { var dogs = getIn(values, 'dogs'); var errors = { dogs: [] }; if (dogs && size(dogs) === 0) { errors.dogs._error = 'No dogs'; } if (dogs && size(dogs) > 1) { errors.dogs._error = 'Too many'; } return errors; } })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var addButton = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithClass(dom, 'add'); var removeButton = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithClass(dom, 'remove'); // length is 0, ERROR! expect(renderFieldArray).toHaveBeenCalled(); expect(renderFieldArray.calls.length).toBe(1); expect(renderFieldArray.calls[0].arguments[0].fields.length).toBe(0); expect(renderFieldArray.calls[0].arguments[0].meta.error).toExist().toBe('No dogs'); _reactAddonsTestUtils2.default.Simulate.click(addButton); // length goes to 1, no error yet expect(renderFieldArray.calls.length).toBe(2); expect(renderFieldArray.calls[1].arguments[0].fields.length).toBe(1); expect(renderFieldArray.calls[1].arguments[0].meta.error).toNotExist(); _reactAddonsTestUtils2.default.Simulate.click(addButton); // length goes to 2, ERROR! expect(renderFieldArray.calls.length).toBe(3); expect(renderFieldArray.calls[2].arguments[0].fields.length).toBe(2); expect(renderFieldArray.calls[2].arguments[0].meta.error).toExist().toBe('Too many'); _reactAddonsTestUtils2.default.Simulate.click(removeButton); // length goes to 1, ERROR disappears! expect(renderFieldArray.calls.length).toBe(4); expect(renderFieldArray.calls[3].arguments[0].fields.length).toBe(1); expect(renderFieldArray.calls[3].arguments[0].meta.error).toNotExist(); _reactAddonsTestUtils2.default.Simulate.click(removeButton); // length goes to 0, ERROR! expect(renderFieldArray.calls.length).toBe(5); expect(renderFieldArray.calls[4].arguments[0].fields.length).toBe(0); expect(renderFieldArray.calls[4].arguments[0].meta.error).toExist().toBe('No dogs'); }); it('should NOT rerender when a value changes', function () { var store = makeStore({ testForm: { values: { dogs: ['Fido', 'Snoopy'] } } }); var renderField = (0, _expect.createSpy)(function (props) { return _react2.default.createElement('input', props.input); }).andCallThrough(); var renderFieldArray = (0, _expect.createSpy)(function (_ref4) { var fields = _ref4.fields; return _react2.default.createElement( 'div', null, fields.map(function (field) { return _react2.default.createElement(Field, { name: field, component: renderField, key: field }); }) ); }).andCallThrough(); var Form = function (_Component18) { _inherits(Form, _Component18); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement(FieldArray, { name: 'dogs', component: renderFieldArray }); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); // field array rendered expect(renderFieldArray).toHaveBeenCalled(); expect(renderFieldArray.calls.length).toBe(1); // both fields rendered expect(renderField).toHaveBeenCalled(); expect(renderField.calls.length).toBe(2); expect(renderField.calls[0].arguments[0].input.value).toBe('Fido'); // change first field renderField.calls[0].arguments[0].input.onChange('Odie'); // first field rerendered, second field is NOT expect(renderField.calls.length).toBe(3); expect(renderField.calls[2].arguments[0].input.name).toBe('dogs[0]'); expect(renderField.calls[2].arguments[0].input.value).toBe('Odie'); // field array NOT rerendered expect(renderFieldArray.calls.length).toBe(1); }); it('should create a list in the store on push(undefined)', function () { var store = makeStore({}); var renderField = (0, _expect.createSpy)(function (props) { return _react2.default.createElement('input', props.input); }).andCallThrough(); var renderFieldArray = (0, _expect.createSpy)(function (_ref5) { var fields = _ref5.fields; return _react2.default.createElement( 'div', null, fields.map(function (field) { return _react2.default.createElement(Field, { name: field, component: renderField, key: field }); }), _react2.default.createElement( 'button', { onClick: function onClick() { return fields.push(); } }, 'Add Dog' ) ); }).andCallThrough(); var Form = function (_Component19) { _inherits(Form, _Component19); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement(FieldArray, { name: 'dogs', component: renderFieldArray }); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var button = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithTag(dom, 'button'); // only registered field array in store expect(store.getState()).toEqualMap({ form: { testForm: { registeredFields: [{ name: 'dogs', type: 'FieldArray' }] } } }); // length is 0 expect(renderFieldArray).toHaveBeenCalled(); expect(renderFieldArray.calls.length).toBe(1); expect(renderFieldArray.calls[0].arguments[0].fields.length).toBe(0); // add field _reactAddonsTestUtils2.default.Simulate.click(button); // field array rerendered expect(renderFieldArray.calls.length).toBe(2); expect(renderFieldArray.calls[1].arguments[0].fields.length).toBe(1); // field rendered expect(renderField).toHaveBeenCalled(); expect(renderField.calls.length).toBe(1); expect(renderField.calls[0].arguments[0].input.name).toBe('dogs[0]'); expect(renderField.calls[0].arguments[0].input.value).toBe(''); // field registered in store expect(store.getState()).toEqualMap({ form: { testForm: { values: { dogs: [undefined] }, registeredFields: [{ name: 'dogs', type: 'FieldArray' }, { name: 'dogs[0]', type: 'Field' }] } } }); // values list is a list expect(getIn(store.getState(), 'form.testForm.values.dogs')).toBeAList(); }); it('should create a list in the store on push(value)', function () { var store = makeStore({}); var renderField = (0, _expect.createSpy)(function (props) { return _react2.default.createElement('input', props.input); }).andCallThrough(); var renderFieldArray = (0, _expect.createSpy)(function (_ref6) { var fields = _ref6.fields; return _react2.default.createElement( 'div', null, fields.map(function (field) { return _react2.default.createElement(Field, { name: field, component: renderField, key: field }); }), _react2.default.createElement( 'button', { onClick: function onClick() { return fields.push('Fido'); } }, 'Add Dog' ) ); }).andCallThrough(); var Form = function (_Component20) { _inherits(Form, _Component20); function Form() { _classCallCheck(this, Form); return _possibleConstructorReturn(this, (Form.__proto__ || Object.getPrototypeOf(Form)).apply(this, arguments)); } _createClass(Form, [{ key: 'render', value: function render() { return _react2.default.createElement(FieldArray, { name: 'dogs', component: renderFieldArray }); } }]); return Form; }(_react.Component); var TestForm = reduxForm({ form: 'testForm' })(Form); var dom = _reactAddonsTestUtils2.default.renderIntoDocument(_react2.default.createElement( _reactRedux.Provider, { store: store }, _react2.default.createElement(TestForm, null) )); var button = _reactAddonsTestUtils2.default.findRenderedDOMComponentWithTag(dom, 'button'); // only registered field array in store expect(store.getState()).toEqualMap({ form: { testForm: { registeredFields: [{ name: 'dogs', type: 'FieldArray' }] } } }); // length is 0 expect(renderFieldArray).toHaveBeenCalled(); expect(renderFieldArray.calls.length).toBe(1); expect(renderFieldArray.calls[0].arguments[0].fields.length).toBe(0); // add field _reactAddonsTestUtils2.default.Simulate.click(button); // field array rerendered expect(renderFieldArray.calls.length).toBe(2); expect(renderFieldArray.calls[1].arguments[0].fields.length).toBe(1); // field rendered expect(renderField).toHaveBeenCalled(); expect(renderField.calls.length).toBe(1); expect(renderField.calls[0].arguments[0].input.name).toBe('dogs[0]'); expect(renderField.calls[0].arguments[0].input.value).toBe('Fido'); // field registered in store expect(store.getState()).toEqualMap({ form: { testForm: { values: { dogs: ['Fido'] }, registeredFields: [{ name: 'dogs', type: 'FieldArray' }, { name: 'dogs[0]', type: 'Field' }] } } }); // values list is a list expect(getIn(store.getState(), 'form.testForm.values.dogs')).toBeAList(); }); it('should create a list in the store on unshift(undefined)', function () { var store = makeStore({}); var renderField = (0, _expect.createSpy)(function (props) { return _react2.default.createElement('input', props.input); }).andCallThrough(); var renderFieldArray = (0, _expect.createSpy)(function (_ref7) { var fields = _ref7.fields; return _react2.default.createElement( 'div', null, fields.map(function (field) { return _react2.default.createElement(Field, { name: field, component: renderField, key: field }); }), _react2.default.createElement( 'button', { onClick: function onClick() { return fields.unshift(); } }, 'Add Dog' ) ); }).andCallThrough(); var Form = function (_Component21) { _inherits(Form, _Com