测试时无法访问浅层渲染组件 - 找到0个节点

时间:2018-03-08 11:36:21

标签: reactjs jestjs redux-form enzyme

我正在尝试使用JEST和酶对我的React组件进行单元测试。 在这种情况下,我想测试一个redux-form组件,所以我尝试按照本指南: https://github.com/tylercollier/redux-form-test/blob/master/tests/unit/index.js#L10

但我总是收到错误:Method “simulate” is only meant to be run on a single node. 0 found instead.

我意识到这是因为它无法找到我在.find('someElement')中找到的元素,但我无法弄清楚如何正确访问它。我尝试将form中的subject.find('form')更改为MenuInputFieldsinputItemList,但结果是一样的。

修改

我发现错误存在是因为组件以redux形式包装:

MenuInputFields = reduxForm({
  form: 'inputItemList',
  validate
})(MenuInputFields)

删除它可以对组件进行某种程度的测试,但这当然不是最佳的。当使用redux-forms删除连接时,我能够访问表单,但不能访问其中的任何元素,访问除表单之外的任何内容总是会产生与之前相同的错误(显示在上面)。 在我删除了redux-form-wrapping之后,我已将subject.debug()的输出更改为结果,现在您可以看到我的字段实际上在表单中,我无法访问它们。我还更新了测试用例,以显示哪些有效,哪些无效。

我的测试:

import React from 'react'
import configureStore from 'redux-mock-store'
import Adapter from 'enzyme-adapter-react-15'
import * as sinon from 'sinon'
import * as Enzyme from 'enzyme'
import { Provider } from 'react-redux'
import { mount, shallow, render } from 'enzyme'
import { menuList } from '../../stubs/menuList'
import { MenuInputFields } from '../../components/adminMenuInputFields'

Enzyme.configure({ adapter: new Adapter() })

describe('<MenuInputFields />', () => {

  let subject
  let handleSubmit, pristine, reset, submitting, submitForm, touched, error

  beforeEach(() => {
    submitting = false
    pristine = true
    error = null
    reset = sinon.spy()
    handleSubmit = fn => fn
  })
  const buildSubject = () => {
    submitForm = sinon.stub()
    const props = {
      submitForm,
      initialValues: {
        ClosingTime: '14:00',
        MenuItems: {
          FoodItem: 'test',
          Description: 'test',
          Price: '66'
        }
      },
      handleSubmit,
      reset
    }
    return shallow(<MenuInputFields {...props}/>)
  }

  //This works
  it('it calls submitForm once when submitting', () => {
    subject = buildSubject()
    subject.find('form').simulate('submit')
    expect(submitForm.calledOnce).toBeTruthy()
  })

  //This doesnt work
  it('loads initial value of ClosingTime into input-box ', () => {
    subject = buildSubject()
    let closingTime = subject.find('form')
    expect(closingTime).toEqual('14:00')
  })

  //This doesnt work
  it('Renders the "tilføj" button', () => {
    subject = buildSubject()
    let button = subject.find('.addItemRow')
    expect(button.text()).toEqual('Tilføj')
  })

})

我的组件

class MenuInputFields extends React.Component {

  constructor(props){
    super(props)
  }  


  render() {

    let currentDate = new Date()
    let formattedDate = currentDate.toLocaleDateString('en-GB')

    const renderField = ({ input, label, type, className, meta: { touched, error } }) => (
      <div>
          <input {...input} type={type} placeholder={label} className={className} />
          {touched && error && <span>{error}</span>}
      </div>
    );

    const renderMenuItem = ({fields, meta: {touched, error, submitFailed }}) => (
      <ul className='adminInputFoodItem'>
        {fields.map((MenuItem, index) => (
          <li key={index}>
            <p className='col-md-1'> {index+1}  - </p>
            <Field
              name={`${MenuItem}.FoodItem`}
              type='text'
              component={renderField}
              label='Titel'
              className='col-md-2'
            />
            <Field
              name={`${MenuItem}.Description`}
              type='text'
              component={renderField}
              label='Beskrivelse'
              className='col-md-6'
            />
            <Field
              name={`${MenuItem}.Price`}
              type='number'
              component={renderField}
              label='Pris'
              className='col-md-1'
            />
            <button 
              type='button'
              title='Fjern'
              onClick={() => fields.remove(index)}
              className='btn btn-default btn-xs remItemRow'
            >Fjern
            </button>
          </li> 
        ))}
          <li>

          </li>
          <li>
            <button
              type='button'
              onClick={() => fields.push({})}
              className='btn btn-default btn-sm addItemRow'
              >Tilføj
            </button>
            {submitFailed && error && <span>{error}</span>} 
          </li> 
      </ul>
    );

    const { handleSubmit, pristine, reset, submitting, submitForm } = this.props

    return (
      <form className='adminInputForm' onSubmit={handleSubmit(submitForm)}>
        <label className='col-md-2' >Dato: {formattedDate}</label>
        <br />
        <br />
          <ul className='adminInputFoodItem'>
            <li>
              <label className='col-md-1'> Lukketid: </label>
              <Field
                name='ClosingTime'
                type='text'
                component={renderField}
                label='TT:mm'
                className='col-md-1'
              />
            </li> 
          </ul> 
        <hr />
        <div>
          <label className='col-md-1'> # </label>
          <label className='col-md-2'> Titel </label>
          <label className='col-md-3'> Beskrivelse </label>
          <label className='col-md-1'> Pris </label>
        </div>
        <br /> 
        <br /> 
        <FieldArray name='MenuItems' component={renderMenuItem} />
        <br />
        <div className=''>
          <button 
            className='btn btn-default'
            type='submit'
            disabled={pristine || submitting}
            >Gem Menu  
          </button>
          <label>Submit besked her</label>
        </div>  
      </form>  
    )
  }
}

MenuInputFields = reduxForm({
  form: 'inputItemList',
  validate
})(MenuInputFields)

export default MenuInputFields

呈现组件的容器:

const mapDispatchToProps = (dispatch) => {
  return {
    setMenu: (menu) => dispatch(setMenu(menu)),
    submitForm: (newMenu) => dispatch(postMenuRequest(newMenu))
  }
}


class AdminSetMenuView extends React.Component {

  constructor(props){
    super(props)
  }

  componentWillMount(){
    this.props.setMenu(this.props.data)
  }   

  render(){


    return(
      <div>
        <AdminRoutes />
        <br />
        <br /> 
        <div>
          <MenuInputFields 
          initialValues={this.props.initialValues}
          submitForm={this.props.submitForm} />
        </div>
      </div>

    )
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(AdminSetMenuView)
来自console.log(subject.debug())的

输出:

 <form className="adminInputForm" onSubmit={[Function: proxy]}>
  <label className="col-md-2">
    Dato:
    3/8/2018
  </label>
  <br />
  <br />
  <ul className="adminInputFoodItem">
    <li>
      <label className="col-md-1">
         Lukketid:
      </label>
      <Field name="ClosingTime" type="text" component={[Function: renderField]} label="TT:mm" className="col-md-1" />
    </li>
  </ul>
  <hr />
  <div>
    <label className="col-md-1">
       #
    </label>
    <label className="col-md-2">
       Titel
    </label>
    <label className="col-md-3">
       Beskrivelse
    </label>
    <label className="col-md-1">
       Pris
    </label>
  </div>
  <br />
  <br />
  <FieldArray name="MenuItems" component={[Function: renderMenuItem]} />
  <br />
  <div className="">
    <button className="btn btn-default" type="submit" disabled={[undefined]}>
      Gem Menu
    </button>
    <label>
      Submit besked her
    </label>
  </div>

0 个答案:

没有答案