title: How to test components wrapped in an antd Form?
body: <p>I've been struggling with this for months, now. Although there's a lot of speculation on the correct way to test antd wrapped components, none of the suggestions worked for this particular component.</p>
  
  <p>So, I have a component which is a modal with an antd form. In this form, I have a few fields: an input, a select and a tree select, nothing too fancy.</p>
  
  <p>It's basically this:</p>
  
  <pre><code>class FormModal extends React.Component {
    static propTypes = {
      data: propTypes.object,
      form: propTypes.object,
      scopes: propTypes.array.isRequired,
      clients: propTypes.array.isRequired,
      treeData: propTypes.array.isRequired,
      isEditing: propTypes.bool.isRequired,
      isSaving: propTypes.bool.isRequired,
      onCancel: propTypes.func.isRequired,
      onSave: propTypes.func.isRequired,
      onFilterTreeData: propTypes.func.isRequired,
      visible: propTypes.bool.isRequired
    }
  
    static defaultProps = {
      data: null,
      form: {}
    }
  
    state = {
      selectedScopes: [],
      newScopes: [],
      inputVisible: false,
      inputValue: ''
    };
  
    componentDidMount() {
      // do stuff
    }
  
    handleSave = () =&gt; {
      // do stuff
    }
  
    handleSelectedScopesChange = (event) =&gt; {
      // do stuff
    }
  
    updateTreeSelect = () =&gt; {
      const { form } = this.props;
      const { selectedScopes } = this.state;
  
      form.setFieldsValue({
        allowedScopes: selectedScopes
      });
    }
  
    handleRemoveTag = (removedTag) =&gt; {
      const selectedScopes = this.state.selectedScopes.filter(scope =&gt; scope !== removedTag);
      const newScopes = this.state.newScopes.filter(scope =&gt; scope !== removedTag);
      this.setState({ selectedScopes, newScopes }, this.updateTreeSelect);
    }
  
    showInput = () =&gt; {
      this.setState({ inputVisible: true }, () =&gt; this.input.focus());
    }
  
    handleInputChange = (e) =&gt; {
      const inputValue = e.target.value;
      this.setState({ inputValue });
    }
  
    handleInputConfirm = () =&gt; {
      const { newScopes, inputValue } = this.state;
      let tags = newScopes;
      if (inputValue &amp;&amp; tags.indexOf(inputValue) === -1) {
        tags = [inputValue, ...tags];
      }
  
      this.setState({
        newScopes: tags,
        inputVisible: false,
        inputValue: '',
      });
    }
  
    saveInputRef = input =&gt; this.input = input
  
    renderTags = (scopeArrays) =&gt; {
      const tags = scopeArrays.map(scopeArray =&gt;
        scopeArray.map((permition) =&gt; {
          let scopeType = null;
          if (permition.includes('read') || permition.includes('get')) scopeType = 'blue';
          if (permition.includes('create') || permition.includes('write') || permition.includes('send')) scopeType = 'green';
          if (permition.includes('update')) scopeType = 'gold';
          if (permition.includes('delete')) scopeType = 'red';
          return (
            &lt;Tag
              key={permition}
              color={scopeType || 'purple'}
              style={{ margin: '2px 4px 2px 0' }}
              closable
              afterClose={() =&gt; this.handleRemoveTag(permition)}
            &gt;
              {permition}
            &lt;/Tag&gt;
          );
        })
      );
  
      return [].concat(...tags);
    }
  
    render() {
      const {
        selectedScopes,
        newScopes,
        inputValue,
        inputVisible
      } = this.state;
  
      const {
        form,
        treeData,
        clients,
        isEditing,
        isSaving,
        onCancel,
        onFilterTreeData,
        visible
      } = this.props;
  
      const {
        getFieldDecorator,
        getFieldsError,
      } = form;
  
      const selectedScopesTags = this.renderTags([newScopes, selectedScopes]);
  
      const clientOptions = clients.map(client =&gt; (&lt;Option key={client._id}&gt;{client.name}&lt;/Option&gt;));
  
      return (
        &lt;Modal
          className="user-modal"
          title={isEditing ? 'Editing Group' : 'Creating Group'}
          visible={visible}
          onCancel={onCancel}
          footer={[
            &lt;Button key="cancel" onClick={onCancel}&gt;Cancel&lt;/Button&gt;,
            &lt;Button
              key="save"
              type="primary"
              loading={isSaving}
              onClick={this.handleSave}
              disabled={formRules.hasErrors(getFieldsError())}
            &gt;
              Save
            &lt;/Button&gt;
          ]}
        &gt;
          &lt;Form layout="vertical" onSubmit={this.handleSave}&gt;
            &lt;Row gutter={24}&gt;
              &lt;Col span={12}&gt;
                &lt;FormItem label="Name"&gt;
                  {getFieldDecorator(
                    'name',
                    { rules: [formRules.required, { max: 20, message: 'Group name can\'t excede 20 characters' }] }
                  )(
                    &lt;Input /&gt;
                  )}
                &lt;/FormItem&gt;
              &lt;/Col&gt;
              &lt;Col span={12}&gt;
                &lt;FormItem label="Client"&gt;
                  {getFieldDecorator(
                    'client', { rules: [formRules.required] }
                  )(
                    &lt;Select placeholder="Please select client"&gt;
                      {clientOptions}
                    &lt;/Select&gt;
                  )}
                &lt;/FormItem&gt;
              &lt;/Col&gt;
              &lt;Col span={24}&gt;
                &lt;FormItem label="Scopes"&gt;
                  {getFieldDecorator(
                    'allowedScopes'
                  )(
                    &lt;TreeSelect
                      treeData={treeData}
                      filterTreeNode={onFilterTreeData}
                      onChange={this.handleSelectedScopesChange}
                      treeCheckable
                      dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                      showCheckedStrategy="SHOW_PARENT"
                      searchPlaceholder="Filter by scopes"
                      className="groups__filter groups__filter--fill"
                    /&gt;
                  )}
                &lt;/FormItem&gt;
              &lt;/Col&gt;
              &lt;Col span={24}&gt;
                &lt;Card
                  title="Selected Scopes"
                  style={{ width: '100%' }}
                &gt;
                  &lt;div&gt;
                    {inputVisible &amp;&amp; (
                      &lt;Input
                        ref={this.saveInputRef}
                        type="text"
                        size="small"
                        style={{ width: 350 }}
                        value={inputValue}
                        onChange={this.handleInputChange}
                        onBlur={this.handleInputConfirm}
                        onPressEnter={this.handleInputConfirm}
                      /&gt;
                    )}
                    {!inputVisible &amp;&amp; (
                      &lt;Tag
                        onClick={this.showInput}
                        style={{ background: '#fff', borderStyle: 'dashed', margin: '5px 0' }}
                      &gt;
                        &lt;Icon type="plus" /&gt; New Scope
                      &lt;/Tag&gt;
                    )}
                  &lt;/div&gt;
                  { selectedScopesTags.length &gt; 0 ? (
                    selectedScopesTags
                  ) : &lt;p&gt;No scopes selected yet.&lt;/p&gt; }
                &lt;/Card&gt;
              &lt;/Col&gt;
            &lt;/Row&gt;
          &lt;/Form&gt;
        &lt;/Modal&gt;
      );
    }
  }
  
  export default Form.create()(FormModal);
  </code></pre>
  
  <p>I know that this component is urging for a refactoring, but that's not my job right now. I need to UI test this and validate if everything is working properly.</p>
  
  <p>I'm trying to test if the form fields are rendering properly. I'm using Jest and Enzyme and so far I got this:</p>
  
  <pre><code>describe('Groups modal', () =&gt; {
    let props;
    const groupsModal = () =&gt;
      mount(
        &lt;FormModal.WrappedComponent {...props} /&gt;
      )
  
    beforeEach(() =&gt; {
      props = {
        data: null,
        scopes: [],
        clients: [],
        treeData: [],
        isEditing: false,
        isSaving: false,
        onCancel: jest.fn(),
        onSave: jest.fn(),
        onFilterTreeData: jest.fn(),
        visible: true,
        form: {
          getFieldsError: jest.fn(() =&gt; { return {} }),
          getFieldDecorator: () =&gt; (component) =&gt; component
        }
      };
    });
  
    it('should render properly', () =&gt; {
      const wrapperDivChilds = groupsModal().find('.user-modal').children();
  
      expect(wrapperDivChilds.length).toBeGreaterThanOrEqual(1);
    });
  
    describe('form fields', () =&gt; {
      it('should render name input', () =&gt; {
        const nameInput = groupsModal().find(Input);
  
        expect(nameInput.length).toBe(1);
      });
  
      it('should render clients select', () =&gt; {
        const clientsSelect = groupsModal().find(Select);
  
        expect(clientsSelect.length).toBe(1);
      });
  
      it('should render scopes tree select', () =&gt; {
        const scopesTreeSelect = groupsModal().find(TreeSelect);
  
        expect(scopesTreeSelect.length).toBe(1);
      });
    });
  });
  </code></pre>
  
  <p>All of my tests that validate if the inputs were rendered are failing.
  As you can see, I tried mocking the form decorator functions, but still no success...</p>
  
  <p>So, my question is: how should I test this component?</p>