diff --git a/packages/ra-ui-materialui/src/form/SimpleFormIterator.js b/packages/ra-ui-materialui/src/form/SimpleFormIterator.js index 5613e2571b8..f52da4c8e9b 100644 --- a/packages/ra-ui-materialui/src/form/SimpleFormIterator.js +++ b/packages/ra-ui-materialui/src/form/SimpleFormIterator.js @@ -105,7 +105,7 @@ export class SimpleFormIterator extends Component { addField = () => { const { fields } = this.props; this.ids.push(this.nextId++); - fields.push({}); + fields.push(undefined); }; render() { diff --git a/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.js b/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.js new file mode 100644 index 00000000000..5ab41f0827c --- /dev/null +++ b/packages/ra-ui-materialui/src/form/SimpleFormIterator.spec.js @@ -0,0 +1,206 @@ +import { cleanup, fireEvent, wait, getByText } from '@testing-library/react'; +import React from 'react'; +import { renderWithRedux } from 'ra-core'; + +import { SimpleFormIterator } from './SimpleFormIterator'; +import TextInput from '../input/TextInput'; +import { ArrayInput } from '../input'; +import SimpleForm from './SimpleForm'; + +describe('', () => { + afterEach(cleanup); + + it('should display an add item button at least', () => { + const { getByText } = renderWithRedux( + + + x}> + + + + + ); + + expect(getByText('ra.action.add')).toBeDefined(); + }); + + it('should not display add button if disableAdd is truthy', () => { + const { queryAllByText } = renderWithRedux( + + + x} disableAdd> + + + + + ); + + expect(queryAllByText('ra.action.add').length).toBe(0); + }); + + it('should not display remove button if disableRemove is truthy', () => { + const { queryAllByText } = renderWithRedux( + + + x} disableRemove> + + + + + ); + + expect(queryAllByText('ra.action.remove').length).toBe(0); + }); + + it('should add children row on add button click', async () => { + const { + getByText, + queryAllByLabelText, + queryAllByText, + } = renderWithRedux( + + + x}> + + + + + ); + + const addItemElement = getByText('ra.action.add').closest('button'); + + fireEvent.click(addItemElement); + await wait(() => { + const inputElements = queryAllByLabelText( + 'resources.undefined.fields.email' + ); + + expect(inputElements.length).toBe(1); + }); + + fireEvent.click(addItemElement); + await wait(() => { + const inputElements = queryAllByLabelText( + 'resources.undefined.fields.email' + ); + + expect(inputElements.length).toBe(2); + }); + + const inputElements = queryAllByLabelText( + 'resources.undefined.fields.email' + ); + + expect( + inputElements.map(inputElement => ({ email: inputElement.value })) + ).toEqual([{ email: '' }, { email: '' }]); + + expect(queryAllByText('ra.action.remove').length).toBe(2); + }); + + it('should add correct children on add button click without source', async () => { + const { + getByText, + queryAllByLabelText, + queryAllByText, + } = renderWithRedux( + + + x}> + + + + + ); + + const addItemElement = getByText('ra.action.add').closest('button'); + + fireEvent.click(addItemElement); + await wait(() => { + const inputElements = queryAllByLabelText('CustomLabel'); + + expect(inputElements.length).toBe(1); + }); + + const inputElements = queryAllByLabelText('CustomLabel'); + + expect(inputElements.map(inputElement => inputElement.value)).toEqual([ + '', + ]); + + expect(queryAllByText('ra.action.remove').length).toBe(1); + }); + + it('should add correct children with default value on add button click without source', async () => { + const { + getByText, + queryAllByLabelText, + queryAllByText, + } = renderWithRedux( + + + x}> + + + + + ); + + const addItemElement = getByText('ra.action.add').closest('button'); + + fireEvent.click(addItemElement); + await wait(() => { + const inputElements = queryAllByLabelText('CustomLabel'); + + expect(inputElements.length).toBe(1); + }); + + const inputElements = queryAllByLabelText('CustomLabel'); + + expect(inputElements.map(inputElement => inputElement.value)).toEqual([ + '5', + ]); + + expect(queryAllByText('ra.action.remove').length).toBe(1); + }); + + it('should remove children row on remove button click', async () => { + const emails = [{ email: 'foo@bar.com' }, { email: 'bar@foo.com' }]; + + const { queryAllByLabelText } = renderWithRedux( + + + x}> + + + + + ); + + const inputElements = queryAllByLabelText( + 'resources.undefined.fields.email' + ); + + expect( + inputElements.map(inputElement => ({ email: inputElement.value })) + ).toEqual(emails); + + const removeFirstButton = getByText( + inputElements[0].closest('li'), + 'ra.action.remove' + ).closest('button'); + + fireEvent.click(removeFirstButton); + await wait(() => { + const inputElements = queryAllByLabelText( + 'resources.undefined.fields.email' + ); + + expect( + inputElements.map(inputElement => ({ + email: inputElement.value, + })) + ).toEqual([{ email: 'bar@foo.com' }]); + }); + }); +});