mirror of
https://github.com/zhigang1992/redux-form.git
synced 2026-04-30 05:15:41 +08:00
separate field array props as voted on #1063
This commit is contained in:
@@ -52,71 +52,73 @@ The following properties and methods are available on an instance of a `FieldArr
|
||||
|
||||
## Props
|
||||
|
||||
These are props that `FieldArray` will pass to your wrapped component.
|
||||
These are props that `FieldArray` will pass to your wrapped component. As you can see, they are
|
||||
all under the `fields` key. Any additional props that you pass to `FieldArray` will be passed
|
||||
along, but will _not_ be under the `fields` key.
|
||||
|
||||
#### `dirty : boolean`
|
||||
#### `fields.dirty : boolean`
|
||||
|
||||
> `true` if the any of the fields in the field array have changed from their initialized value.
|
||||
Opposite of `pristine`.
|
||||
|
||||
#### `error : String` [optional]
|
||||
#### `fields.error : String` [optional]
|
||||
|
||||
> The error for this field array if its value is not passing validation. Both synchronous,
|
||||
asynchronous, and submit validation errors will be reported here. Array-specific errors should be
|
||||
returned from the validation function as an `_error` key on the array.
|
||||
|
||||
#### `forEach(callback) : Function`
|
||||
#### `fields.forEach(callback) : Function`
|
||||
|
||||
> A method to iterate over each value of the array. See the section on [Iteration](#iteration)
|
||||
for more details.
|
||||
|
||||
#### `insert(index, value) : Function`
|
||||
#### `fields.insert(index, value) : Function`
|
||||
|
||||
> A function to insert a new value into the array at any arbitrary index.
|
||||
|
||||
#### `invalid : boolean`
|
||||
#### `fields.invalid : boolean`
|
||||
|
||||
> `true` if the field array value fails validation (has a validation error). Opposite of `valid`.
|
||||
|
||||
#### `length : Number`
|
||||
#### `fields.length : Number`
|
||||
|
||||
> The current length of the array.
|
||||
|
||||
#### `map(callback) : Function`
|
||||
#### `fields.map(callback) : Function`
|
||||
|
||||
> A method to iterate over each value of the array. Returns an array of the results of each call
|
||||
to the callback. See the section on [Iteration](#iteration) for more details.
|
||||
|
||||
#### `pop() : Function`
|
||||
#### `fields.pop() : Function`
|
||||
|
||||
> Removes an item from the end of the array. Returns the item removed.
|
||||
|
||||
#### `pristine : boolean`
|
||||
#### `fields.pristine : boolean`
|
||||
|
||||
> `true` if the all of the fields in the field array are the same as their initialized
|
||||
value. Opposite of `dirty`.
|
||||
|
||||
#### `push(value) : Function`
|
||||
#### `fields.push(value) : Function`
|
||||
|
||||
> Adds a value to the end of the array. Returns nothing.
|
||||
|
||||
#### `remove(index) : Function`
|
||||
#### `fields.remove(index) : Function`
|
||||
|
||||
> Removes an item from the array at an arbitrary index. Returns nothing.
|
||||
|
||||
#### `shift() : Function`
|
||||
#### `fields.shift() : Function`
|
||||
|
||||
> Removes an item from beginning of the array. Returns the item removed..
|
||||
|
||||
#### `swap(indexA, indexB) : Function`
|
||||
#### `fields.swap(indexA, indexB) : Function`
|
||||
|
||||
> Swaps two items in the array at the given indexes. Returns nothing.
|
||||
|
||||
#### `unshift(value) : Function`
|
||||
#### `fields.unshift(value) : Function`
|
||||
|
||||
> Adds an item to the beginning of the array. Returns nothing.
|
||||
|
||||
#### `valid : boolean`
|
||||
#### `fields.valid : boolean`
|
||||
|
||||
> `true` if the field value passes validation (has no validation errors). Opposite of `invalid`.
|
||||
|
||||
|
||||
@@ -12,18 +12,18 @@ const renderField = props => (
|
||||
</div>
|
||||
)
|
||||
|
||||
const renderMembers = members => (
|
||||
const renderMembers = ({ fields }) => (
|
||||
<ul>
|
||||
<li>
|
||||
<button type="button" onClick={() => members.push({})}>Add Member</button>
|
||||
<button type="button" onClick={() => fields.push({})}>Add Member</button>
|
||||
</li>
|
||||
{members.map((member, memberIndex) =>
|
||||
<li key={memberIndex}>
|
||||
{fields.map((member, index) =>
|
||||
<li key={index}>
|
||||
<button
|
||||
type="button"
|
||||
title="Remove Member"
|
||||
onClick={() => members.remove(memberIndex)}/>
|
||||
<h4>Member #{memberIndex + 1}</h4>
|
||||
onClick={() => fields.remove(index)}/>
|
||||
<h4>Member #{index + 1}</h4>
|
||||
<Field
|
||||
name={`${member}.firstName`}
|
||||
type="text"
|
||||
@@ -40,25 +40,25 @@ const renderMembers = members => (
|
||||
</ul>
|
||||
)
|
||||
|
||||
const renderHobbies = hobbies => (
|
||||
const renderHobbies = ({ fields }) => (
|
||||
<ul>
|
||||
<li>
|
||||
<button type="button" onClick={() => hobbies.push()}>Add Hobby</button>
|
||||
<button type="button" onClick={() => fields.push()}>Add Hobby</button>
|
||||
</li>
|
||||
{hobbies.map((hobby, hobbyIndex) =>
|
||||
<li key={hobbyIndex}>
|
||||
{fields.map((hobby, index) =>
|
||||
<li key={index}>
|
||||
<button
|
||||
type="button"
|
||||
title="Remove Hobby"
|
||||
onClick={() => hobbies.remove(hobbyIndex)}/>
|
||||
onClick={() => fields.remove(index)}/>
|
||||
<Field
|
||||
name={hobby}
|
||||
type="text"
|
||||
component={renderField}
|
||||
placeholder={`Hobby #${hobbyIndex + 1}`}/>
|
||||
placeholder={`Hobby #${index + 1}`}/>
|
||||
</li>
|
||||
)}
|
||||
{hobbies.error && <li className="error">{hobbies.error}</li>}
|
||||
{fields.error && <li className="error">{fields.error}</li>}
|
||||
</ul>
|
||||
)
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ const createConnectedField = ({
|
||||
|
||||
render() {
|
||||
const { component, defaultValue, withRef, ...rest } = this.props
|
||||
const { _reduxForm: { adapter } } = this.context
|
||||
const props = createFieldProps(getIn,
|
||||
name,
|
||||
rest,
|
||||
@@ -57,14 +56,7 @@ const createConnectedField = ({
|
||||
if (withRef) {
|
||||
props.ref = 'renderedComponent'
|
||||
}
|
||||
let element
|
||||
if (adapter) {
|
||||
element = adapter(component, props)
|
||||
}
|
||||
if (!element) {
|
||||
element = createElement(component, props)
|
||||
}
|
||||
return element
|
||||
return createElement(component, props)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -454,59 +454,6 @@ const describeField = (name, structure, combineReducers, expect) => {
|
||||
expect(input.calls[ 1 ].arguments[ 0 ].bar).toBe('baz')
|
||||
})
|
||||
|
||||
it('should use adapter to render fields', () => {
|
||||
const store = makeStore({
|
||||
testForm: {
|
||||
values: {
|
||||
cow: 'calf',
|
||||
horse: 'foal',
|
||||
sheep: 'lamb',
|
||||
donkey: 'foal',
|
||||
chicken: 'chick'
|
||||
}
|
||||
}
|
||||
})
|
||||
const adapter = createSpy(props => <div {...props}/>).andCallThrough()
|
||||
class Form extends Component {
|
||||
render() {
|
||||
return (<div>
|
||||
<Field name="cow" component="Cow" says="moo"/>
|
||||
<Field name="horse" component="Horse" says="neigh"/>
|
||||
<Field name="sheep" component="Sheep" says="baa"/>
|
||||
<Field name="donkey" component="Donkey" says="heehaw"/>
|
||||
<Field name="chicken" component="Chicken" says="cluck"/>
|
||||
</div>)
|
||||
}
|
||||
}
|
||||
const TestForm = reduxForm({
|
||||
form: 'testForm',
|
||||
adapter
|
||||
})(Form)
|
||||
TestUtils.renderIntoDocument(
|
||||
<Provider store={store}>
|
||||
<TestForm/>
|
||||
</Provider>
|
||||
)
|
||||
expect(adapter).toHaveBeenCalled()
|
||||
expect(adapter.calls.length).toBe(5)
|
||||
expect(adapter.calls[ 0 ].arguments[ 0 ]).toBe('Cow')
|
||||
expect(adapter.calls[ 0 ].arguments[ 1 ].says).toBe('moo')
|
||||
expect(adapter.calls[ 0 ].arguments[ 1 ].value).toBe('calf')
|
||||
expect(adapter.calls[ 1 ].arguments[ 0 ]).toBe('Horse')
|
||||
expect(adapter.calls[ 1 ].arguments[ 1 ].says).toBe('neigh')
|
||||
expect(adapter.calls[ 1 ].arguments[ 1 ].value).toBe('foal')
|
||||
expect(adapter.calls[ 2 ].arguments[ 0 ]).toBe('Sheep')
|
||||
expect(adapter.calls[ 2 ].arguments[ 1 ].says).toBe('baa')
|
||||
expect(adapter.calls[ 2 ].arguments[ 1 ].value).toBe('lamb')
|
||||
expect(adapter.calls[ 3 ].arguments[ 0 ]).toBe('Donkey')
|
||||
expect(adapter.calls[ 3 ].arguments[ 1 ].says).toBe('heehaw')
|
||||
expect(adapter.calls[ 3 ].arguments[ 1 ].value).toBe('foal')
|
||||
expect(adapter.calls[ 4 ].arguments[ 0 ]).toBe('Chicken')
|
||||
expect(adapter.calls[ 4 ].arguments[ 1 ].says).toBe('cluck')
|
||||
expect(adapter.calls[ 4 ].arguments[ 1 ].value).toBe('chick')
|
||||
|
||||
})
|
||||
|
||||
// ----------------------------------------------
|
||||
// Uncomment this to confirm that #1024 is fixed.
|
||||
// ----------------------------------------------
|
||||
|
||||
@@ -66,7 +66,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
foo: [ 'a', 'b', 'c' ]
|
||||
}
|
||||
})
|
||||
expect(props.length).toBe(3)
|
||||
expect(props.fields.length).toBe(3)
|
||||
})
|
||||
|
||||
it('should be okay with no array value', () => {
|
||||
@@ -74,9 +74,9 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
const props = testProps({
|
||||
values: {}
|
||||
})
|
||||
expect(props.length).toBe(0)
|
||||
props.forEach(iterate)
|
||||
props.map(iterate)
|
||||
expect(props.fields.length).toBe(0)
|
||||
props.fields.forEach(iterate)
|
||||
props.fields.map(iterate)
|
||||
expect(iterate).toNotHaveBeenCalled()
|
||||
})
|
||||
|
||||
@@ -89,8 +89,8 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
foo: [ 'a', 'b', 'c' ]
|
||||
}
|
||||
})
|
||||
expect(props1.pristine).toBe(true)
|
||||
expect(props1.dirty).toBe(false)
|
||||
expect(props1.fields.pristine).toBe(true)
|
||||
expect(props1.fields.dirty).toBe(false)
|
||||
const props2 = testProps({
|
||||
initial: {
|
||||
foo: [ 'a', 'b', 'c' ]
|
||||
@@ -99,15 +99,49 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
foo: [ 'a', 'b' ]
|
||||
}
|
||||
})
|
||||
expect(props2.pristine).toBe(false)
|
||||
expect(props2.dirty).toBe(true)
|
||||
expect(props2.fields.pristine).toBe(false)
|
||||
expect(props2.fields.dirty).toBe(true)
|
||||
})
|
||||
|
||||
it('should provide pass through other props', () => {
|
||||
const store = makeStore({
|
||||
testForm: {
|
||||
values: {
|
||||
foo: [ 'bar' ]
|
||||
}
|
||||
}
|
||||
})
|
||||
const renderArray = createSpy(() => <div/>).andCallThrough()
|
||||
class Form extends Component {
|
||||
render() {
|
||||
return <div>
|
||||
<FieldArray
|
||||
name="foo"
|
||||
component={renderArray}
|
||||
otherProp="dog"
|
||||
anotherProp="cat"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
const TestForm = reduxForm({ form: 'testForm' })(Form)
|
||||
TestUtils.renderIntoDocument(
|
||||
<Provider store={store}>
|
||||
<TestForm/>
|
||||
</Provider>
|
||||
)
|
||||
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', () => {
|
||||
const store = makeStore({
|
||||
testForm: {
|
||||
values: {
|
||||
foo: 'bar'
|
||||
foo: [ 'bar' ]
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -139,9 +173,9 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
foo: [ 'a', 'b', 'c' ]
|
||||
}
|
||||
})
|
||||
expect(props.length).toBe(3)
|
||||
expect(props.fields.length).toBe(3)
|
||||
const iterate = createSpy()
|
||||
props.forEach(iterate)
|
||||
props.fields.forEach(iterate)
|
||||
expect(iterate).toHaveBeenCalled()
|
||||
expect(iterate.calls.length).toBe(3)
|
||||
expect(iterate.calls[ 0 ].arguments[ 0 ]).toBe('foo[0]')
|
||||
@@ -157,7 +191,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
}, {
|
||||
validate: () => ({ foo: { _error: 'foo error' } })
|
||||
})
|
||||
expect(props.error).toBe('foo error')
|
||||
expect(props.fields.error).toBe('foo error')
|
||||
})
|
||||
|
||||
it('should get async errors from Redux state', () => {
|
||||
@@ -171,7 +205,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
}
|
||||
}
|
||||
})
|
||||
expect(props.error).toBe('foo error')
|
||||
expect(props.fields.error).toBe('foo error')
|
||||
})
|
||||
|
||||
it('should get submit errors from Redux state', () => {
|
||||
@@ -185,7 +219,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
}
|
||||
}
|
||||
})
|
||||
expect(props.error).toBe('foo error')
|
||||
expect(props.fields.error).toBe('foo error')
|
||||
})
|
||||
|
||||
it('should provide name getter', () => {
|
||||
@@ -210,7 +244,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
const stub = TestUtils.findRenderedComponentWithType(dom, FieldArray)
|
||||
expect(stub.name).toEqual('foo')
|
||||
})
|
||||
|
||||
|
||||
it('should provide value getter', () => {
|
||||
const store = makeStore({
|
||||
testForm: {
|
||||
@@ -358,21 +392,21 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
}
|
||||
]
|
||||
})
|
||||
const renderArray = ({ fields }) =>
|
||||
<div>
|
||||
{fields.map((name, index) =>
|
||||
<div key={index}>
|
||||
<Field name={`${name}.library`} component="input"/>
|
||||
<Field name={`${name}.author`} component="input"/>
|
||||
<Field name={name} component={props => <strong>{props.error}</strong>}/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
class Form extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<FieldArray name="foo" component={array =>
|
||||
<div>
|
||||
{array.map((name, index) =>
|
||||
<div key={index}>
|
||||
<Field name={`${name}.library`} component="input"/>
|
||||
<Field name={`${name}.author`} component="input"/>
|
||||
<Field name={name} component={props => <strong>{props.error}</strong>}/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
}/>
|
||||
<FieldArray name="foo" component={renderArray}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -401,7 +435,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
}
|
||||
}
|
||||
})
|
||||
const input = createSpy(() => <div/>).andCallThrough()
|
||||
const component = createSpy(() => <div/>).andCallThrough()
|
||||
class Form extends Component {
|
||||
constructor() {
|
||||
super()
|
||||
@@ -410,7 +444,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
|
||||
render() {
|
||||
return (<div>
|
||||
<FieldArray name={this.state.field} component={input}/>
|
||||
<FieldArray name={this.state.field} component={component}/>
|
||||
<button onClick={() => this.setState({ field: 'bar' })}>Change</button>
|
||||
</div>)
|
||||
}
|
||||
@@ -421,20 +455,20 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
<TestForm/>
|
||||
</Provider>
|
||||
)
|
||||
expect(input).toHaveBeenCalled()
|
||||
expect(input.calls.length).toBe(1)
|
||||
expect(input.calls[ 0 ].arguments[ 0 ].length).toBe(2)
|
||||
expect(component).toHaveBeenCalled()
|
||||
expect(component.calls.length).toBe(1)
|
||||
expect(component.calls[ 0 ].arguments[ 0 ].fields.length).toBe(2)
|
||||
|
||||
const button = TestUtils.findRenderedDOMComponentWithTag(dom, 'button')
|
||||
TestUtils.Simulate.click(button)
|
||||
|
||||
expect(input.calls.length).toBe(2)
|
||||
expect(input.calls[ 1 ].arguments[ 0 ].length).toBe(1)
|
||||
expect(component.calls.length).toBe(2)
|
||||
expect(component.calls[ 1 ].arguments[ 0 ].fields.length).toBe(1)
|
||||
})
|
||||
|
||||
it('should reconnect when props change', () => {
|
||||
const store = makeStore()
|
||||
const input = createSpy(() => <div/>).andCallThrough()
|
||||
const component = createSpy(() => <div/>).andCallThrough()
|
||||
class Form extends Component {
|
||||
constructor() {
|
||||
super()
|
||||
@@ -443,7 +477,7 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
|
||||
render() {
|
||||
return (<div>
|
||||
<FieldArray name="foo" foo={this.state.foo} bar={this.state.bar} component={input}/>
|
||||
<FieldArray name="foo" foo={this.state.foo} bar={this.state.bar} component={component}/>
|
||||
<button onClick={() => this.setState({ foo: 'qux', bar: 'baz' })}>Change</button>
|
||||
</div>)
|
||||
}
|
||||
@@ -454,17 +488,17 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
<TestForm/>
|
||||
</Provider>
|
||||
)
|
||||
expect(input).toHaveBeenCalled()
|
||||
expect(input.calls.length).toBe(1)
|
||||
expect(input.calls[ 0 ].arguments[ 0 ].foo).toBe('foo')
|
||||
expect(input.calls[ 0 ].arguments[ 0 ].bar).toBe('bar')
|
||||
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')
|
||||
|
||||
const button = TestUtils.findRenderedDOMComponentWithTag(dom, 'button')
|
||||
TestUtils.Simulate.click(button)
|
||||
|
||||
expect(input.calls.length).toBe(2)
|
||||
expect(input.calls[ 1 ].arguments[ 0 ].foo).toBe('qux')
|
||||
expect(input.calls[ 1 ].arguments[ 0 ].bar).toBe('baz')
|
||||
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 array sync error appears or disappears', () => {
|
||||
@@ -476,10 +510,10 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
}
|
||||
})
|
||||
const renderFieldArray =
|
||||
createSpy(dogs => (<div>
|
||||
{dogs.map((dog, index) => <input key={index} {...dog}/>)}
|
||||
<button className="add" onClick={() => dogs.push()}>Add Dog</button>
|
||||
<button className="remove" onClick={() => dogs.pop()}>Remove Dog</button>
|
||||
createSpy(({ fields }) => (<div>
|
||||
{fields.map((field, index) => <input key={index} {...field}/>)}
|
||||
<button className="add" onClick={() => fields.push()}>Add Dog</button>
|
||||
<button className="remove" onClick={() => fields.pop()}>Remove Dog</button>
|
||||
</div>)).andCallThrough()
|
||||
class Form extends Component {
|
||||
render() {
|
||||
@@ -513,36 +547,36 @@ const describeFieldArray = (name, structure, combineReducers, expect) => {
|
||||
// length is 0, ERROR!
|
||||
expect(renderFieldArray).toHaveBeenCalled()
|
||||
expect(renderFieldArray.calls.length).toBe(1)
|
||||
expect(renderFieldArray.calls[ 0 ].arguments[ 0 ].length).toBe(0)
|
||||
expect(renderFieldArray.calls[ 0 ].arguments[ 0 ].error)
|
||||
expect(renderFieldArray.calls[ 0 ].arguments[ 0 ].fields.length).toBe(0)
|
||||
expect(renderFieldArray.calls[ 0 ].arguments[ 0 ].fields.error)
|
||||
.toExist()
|
||||
.toBe('No dogs')
|
||||
|
||||
TestUtils.Simulate.click(addButton) // length goes to 1, no error yet
|
||||
|
||||
expect(renderFieldArray.calls.length).toBe(2)
|
||||
expect(renderFieldArray.calls[ 1 ].arguments[ 0 ].length).toBe(1)
|
||||
expect(renderFieldArray.calls[ 1 ].arguments[ 0 ].error).toNotExist()
|
||||
expect(renderFieldArray.calls[ 1 ].arguments[ 0 ].fields.length).toBe(1)
|
||||
expect(renderFieldArray.calls[ 1 ].arguments[ 0 ].fields.error).toNotExist()
|
||||
|
||||
TestUtils.Simulate.click(addButton) // length goes to 2, ERROR!
|
||||
|
||||
expect(renderFieldArray.calls.length).toBe(3)
|
||||
expect(renderFieldArray.calls[ 2 ].arguments[ 0 ].length).toBe(2)
|
||||
expect(renderFieldArray.calls[ 2 ].arguments[ 0 ].error)
|
||||
expect(renderFieldArray.calls[ 2 ].arguments[ 0 ].fields.length).toBe(2)
|
||||
expect(renderFieldArray.calls[ 2 ].arguments[ 0 ].fields.error)
|
||||
.toExist()
|
||||
.toBe('Too many')
|
||||
|
||||
TestUtils.Simulate.click(removeButton) // length goes to 1, ERROR disappears!
|
||||
|
||||
expect(renderFieldArray.calls.length).toBe(4)
|
||||
expect(renderFieldArray.calls[ 3 ].arguments[ 0 ].length).toBe(1)
|
||||
expect(renderFieldArray.calls[ 3 ].arguments[ 0 ].error).toNotExist()
|
||||
expect(renderFieldArray.calls[ 3 ].arguments[ 0 ].fields.length).toBe(1)
|
||||
expect(renderFieldArray.calls[ 3 ].arguments[ 0 ].fields.error).toNotExist()
|
||||
|
||||
TestUtils.Simulate.click(removeButton) // length goes to 0, ERROR!
|
||||
|
||||
expect(renderFieldArray.calls.length).toBe(5)
|
||||
expect(renderFieldArray.calls[ 4 ].arguments[ 0 ].length).toBe(0)
|
||||
expect(renderFieldArray.calls[ 4 ].arguments[ 0 ].error)
|
||||
expect(renderFieldArray.calls[ 4 ].arguments[ 0 ].fields.length).toBe(0)
|
||||
expect(renderFieldArray.calls[ 4 ].arguments[ 0 ].fields.error)
|
||||
.toExist()
|
||||
.toBe('No dogs')
|
||||
})
|
||||
|
||||
@@ -19,58 +19,58 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
dirty: false,
|
||||
pristine: true
|
||||
}).dirty).toBe(false)
|
||||
}).fields.dirty).toBe(false)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
dirty: false,
|
||||
pristine: true
|
||||
}).pristine).toBe(true)
|
||||
}).fields.pristine).toBe(true)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
dirty: true,
|
||||
pristine: false
|
||||
}).dirty).toBe(true)
|
||||
}).fields.dirty).toBe(true)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
dirty: true,
|
||||
pristine: false
|
||||
}).pristine).toBe(false)
|
||||
}).fields.pristine).toBe(false)
|
||||
})
|
||||
|
||||
it('should provide length', () => {
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
value: fromJS([])
|
||||
}).length).toBe(0)
|
||||
}).fields.length).toBe(0)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
value: fromJS([ 'a' ])
|
||||
}).length).toBe(1)
|
||||
}).fields.length).toBe(1)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
value: fromJS([ 'a', 'b' ])
|
||||
}).length).toBe(2)
|
||||
}).fields.length).toBe(2)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
value: fromJS([ 'a', 'b', 'c' ])
|
||||
}).length).toBe(3)
|
||||
}).fields.length).toBe(3)
|
||||
})
|
||||
|
||||
it('should provide errors', () => {
|
||||
expect(createFieldArrayProps(...defaultProps, {}, 'Sync Error').error).toBe('Sync Error')
|
||||
expect(createFieldArrayProps(...defaultProps, {}, 'Sync Error').valid).toBe(false)
|
||||
expect(createFieldArrayProps(...defaultProps, {}, 'Sync Error').invalid).toBe(true)
|
||||
expect(createFieldArrayProps(...defaultProps, {}, 'Sync Error').fields.error).toBe('Sync Error')
|
||||
expect(createFieldArrayProps(...defaultProps, {}, 'Sync Error').fields.valid).toBe(false)
|
||||
expect(createFieldArrayProps(...defaultProps, {}, 'Sync Error').fields.invalid).toBe(true)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
asyncError: 'Async Error'
|
||||
}).error).toBe('Async Error')
|
||||
}).fields.error).toBe('Async Error')
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
asyncError: 'Async Error'
|
||||
}).valid).toBe(false)
|
||||
}).fields.valid).toBe(false)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
asyncError: 'Async Error'
|
||||
}).invalid).toBe(true)
|
||||
}).fields.invalid).toBe(true)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
submitError: 'Submit Error'
|
||||
}).error).toBe('Submit Error')
|
||||
}).fields.error).toBe('Submit Error')
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
submitError: 'Submit Error'
|
||||
}).valid).toBe(false)
|
||||
}).fields.valid).toBe(false)
|
||||
expect(createFieldArrayProps(...defaultProps, {
|
||||
submitError: 'Submit Error'
|
||||
}).invalid).toBe(true)
|
||||
}).fields.invalid).toBe(true)
|
||||
})
|
||||
|
||||
it('should provide push', () => {
|
||||
@@ -79,9 +79,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
value: fromJS([ 'a', 'b' ]),
|
||||
arrayPush
|
||||
})
|
||||
expect(result.push).toBeA('function')
|
||||
expect(result.fields.push).toBeA('function')
|
||||
expect(arrayPush).toNotHaveBeenCalled()
|
||||
expect(result.push('c')).toNotExist()
|
||||
expect(result.fields.push('c')).toNotExist()
|
||||
expect(arrayPush)
|
||||
.toHaveBeenCalled()
|
||||
.toHaveBeenCalledWith('c')
|
||||
@@ -93,9 +93,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
value: fromJS([ 'a', 'b', 'c' ]),
|
||||
arrayPop
|
||||
})
|
||||
expect(result.pop).toBeA('function')
|
||||
expect(result.fields.pop).toBeA('function')
|
||||
expect(arrayPop).toNotHaveBeenCalled()
|
||||
expect(result.pop()).toBe('c')
|
||||
expect(result.fields.pop()).toBe('c')
|
||||
expect(arrayPop)
|
||||
.toHaveBeenCalled()
|
||||
.toHaveBeenCalledWith()
|
||||
@@ -107,9 +107,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
value: fromJS([ 'a', 'b' ]),
|
||||
arrayInsert
|
||||
})
|
||||
expect(result.insert).toBeA('function')
|
||||
expect(result.fields.insert).toBeA('function')
|
||||
expect(arrayInsert).toNotHaveBeenCalled()
|
||||
expect(result.insert(1, 'c')).toNotExist()
|
||||
expect(result.fields.insert(1, 'c')).toNotExist()
|
||||
expect(arrayInsert)
|
||||
.toHaveBeenCalled()
|
||||
.toHaveBeenCalledWith(1, 'c')
|
||||
@@ -121,9 +121,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
value: fromJS([ 'a', 'b' ]),
|
||||
arrayRemove
|
||||
})
|
||||
expect(result.remove).toBeA('function')
|
||||
expect(result.fields.remove).toBeA('function')
|
||||
expect(arrayRemove).toNotHaveBeenCalled()
|
||||
expect(result.remove(2)).toNotExist()
|
||||
expect(result.fields.remove(2)).toNotExist()
|
||||
expect(arrayRemove)
|
||||
.toHaveBeenCalled()
|
||||
.toHaveBeenCalledWith(2)
|
||||
@@ -135,9 +135,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
value: fromJS([ 'a', 'b' ]),
|
||||
arrayUnshift
|
||||
})
|
||||
expect(result.unshift).toBeA('function')
|
||||
expect(result.fields.unshift).toBeA('function')
|
||||
expect(arrayUnshift).toNotHaveBeenCalled()
|
||||
expect(result.unshift('c')).toNotExist()
|
||||
expect(result.fields.unshift('c')).toNotExist()
|
||||
expect(arrayUnshift)
|
||||
.toHaveBeenCalled()
|
||||
.toHaveBeenCalledWith('c')
|
||||
@@ -149,9 +149,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
value: fromJS([ 'a', 'b', 'c' ]),
|
||||
arrayShift
|
||||
})
|
||||
expect(result.shift).toBeA('function')
|
||||
expect(result.fields.shift).toBeA('function')
|
||||
expect(arrayShift).toNotHaveBeenCalled()
|
||||
expect(result.shift()).toBe('a')
|
||||
expect(result.fields.shift()).toBe('a')
|
||||
expect(arrayShift)
|
||||
.toHaveBeenCalled()
|
||||
.toHaveBeenCalledWith()
|
||||
@@ -162,9 +162,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
const result = createFieldArrayProps(...defaultProps, {
|
||||
value: fromJS([ 'a', 'b', 'c' ])
|
||||
})
|
||||
expect(result.forEach).toBeA('function')
|
||||
expect(result.fields.forEach).toBeA('function')
|
||||
expect(callback).toNotHaveBeenCalled()
|
||||
result.forEach(callback)
|
||||
result.fields.forEach(callback)
|
||||
expect(callback).toHaveBeenCalled()
|
||||
expect(callback.calls.length).toBe(3)
|
||||
expect(callback.calls[ 0 ].arguments).toEqual([ 'foo[0]', 0 ])
|
||||
@@ -177,9 +177,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
const result = createFieldArrayProps(...defaultProps, {
|
||||
value: fromJS([ 'a', 'b', 'c' ])
|
||||
})
|
||||
expect(result.map).toBeA('function')
|
||||
expect(result.fields.map).toBeA('function')
|
||||
expect(callback).toNotHaveBeenCalled()
|
||||
const mapResult = result.map(callback)
|
||||
const mapResult = result.fields.map(callback)
|
||||
expect(size(mapResult), 3)
|
||||
expect(getIn(mapResult, 0)).toEqual({ whatever: true, name: 'foo[0]' })
|
||||
expect(getIn(mapResult, 1)).toEqual({ whatever: true, name: 'foo[1]' })
|
||||
@@ -197,9 +197,9 @@ const describeCreateFieldProps = (name, structure, expect) => {
|
||||
arraySwap,
|
||||
value: fromJS([ 'a', 'b', 'c' ])
|
||||
})
|
||||
expect(result.swap).toBeA('function')
|
||||
expect(result.fields.swap).toBeA('function')
|
||||
expect(arraySwap).toNotHaveBeenCalled()
|
||||
expect(result.swap(0, 2)).toNotExist()
|
||||
expect(result.fields.swap(0, 2)).toNotExist()
|
||||
expect(arraySwap)
|
||||
.toHaveBeenCalled()
|
||||
.toHaveBeenCalledWith(0, 2)
|
||||
|
||||
@@ -7,27 +7,29 @@ const createFieldArrayProps = (getIn, size, name,
|
||||
const error = syncError || asyncError || submitError
|
||||
const length = size(value)
|
||||
return {
|
||||
dirty,
|
||||
error,
|
||||
forEach: callback => (value || []).forEach((item, index) => callback(`${name}[${index}]`, index)),
|
||||
insert: arrayInsert,
|
||||
invalid: !!error,
|
||||
length,
|
||||
map: callback => (value || []).map((item, index) => callback(`${name}[${index}]`, index)),
|
||||
pop: () => {
|
||||
arrayPop()
|
||||
return getIn(value, length - 1)
|
||||
fields: {
|
||||
dirty,
|
||||
error,
|
||||
forEach: callback => (value || []).forEach((item, index) => callback(`${name}[${index}]`, index)),
|
||||
insert: arrayInsert,
|
||||
invalid: !!error,
|
||||
length,
|
||||
map: callback => (value || []).map((item, index) => callback(`${name}[${index}]`, index)),
|
||||
pop: () => {
|
||||
arrayPop()
|
||||
return getIn(value, length - 1)
|
||||
},
|
||||
pristine,
|
||||
push: arrayPush,
|
||||
remove: arrayRemove,
|
||||
shift: () => {
|
||||
arrayShift()
|
||||
return getIn(value, 0)
|
||||
},
|
||||
swap: arraySwap,
|
||||
unshift: arrayUnshift,
|
||||
valid: !error
|
||||
},
|
||||
pristine,
|
||||
push: arrayPush,
|
||||
remove: arrayRemove,
|
||||
shift: () => {
|
||||
arrayShift()
|
||||
return getIn(value, 0)
|
||||
},
|
||||
swap: arraySwap,
|
||||
unshift: arrayUnshift,
|
||||
valid: !error,
|
||||
...rest
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user