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' }]);
+ });
+ });
+});