在酶/反应单元测试中模拟形式变化不会改变字段值



>我正在做一些基本的表单交互测试

const setup = (errors=false) => {
  let props = {
    budget: {}, errors: {},
    onChange: () => {},
    onSave: () => {}
  };
  if (errors === true) {
    props.errors.budgetCategory= "error";
  }
  return shallow(<AddBudgetForm {...props} />);
};

describe("Fluctuating errors based on input values", () => {
  it("Renders an error when a number is present in the cost field", () => {
    let wrapper = setup();
    wrapper.find('[name="budgetCategory"]').simulate('change', { target: { value: '7' } });
    console.log(wrapper.find('[name="budgetCategory"]').props());
  });
});

我分析控制台上的道具,发现value字段仍未定义......

{ className: 'form-control',
  placeholder: 'Enter Name of Budget Category',
  onChange: [Function: onChange],
  value: undefined,
  name: 'budgetCategory' }

理想情况下,我试图测试的是,模拟非数字的按键应该触发 onChange 处理程序将错误传播到表单。

我尝试在设置中添加一个新的onChange处理程序,但没有工作:

  let props = {
    budget: {}, errors: {},
    onChange: (e) => {props.budget.budgetCategory = e.target.value;},
    onSave: () => {}
  };

添加预算表单组件

import React, { Component, PropTypes } from 'react';
import Alert from '../common/Alert';
import TextInput from '../common/TextInput';
const renderDays = () => {
  return Array(31).fill().map((_, i = 1) => <option key={i+1}>{i+1}</option>);
};
const errorsInForm = errors => {
  let error = false;
  Object.keys(errors).map(item => {
    if (errors[item]) { error = true; }
  });
  return error;
};
const generateValidationError = error => {
  return (
    <span style={{color: "red"}}>{error}</span>
  );
};
const AddBudgetForm = ({budget, onChange, onSave, errors}) => {
  return (
    <div name="AddBudgetForm">
      <form>
      {!errorsInForm(errors) &&
        <Alert
          name="add-budget-alert"
          alertType = "alert alert-info"
          fontAwesomeIcon = "fa fa-info"
          alertDescription = " Adding a budget is simple. Add a category such as groceries
          , allocate $200.00 per month and the day you'd like the budget to reset."
        />
      }
      {errorsInForm(errors) &&
        <Alert
          name="add-budget-alert"
          alertType = "alert alert-danger"
          fontAwesomeIcon = "fa fa-warning"
          alertDescription = " There are problems with the form submission. Ensure all values in the form are valid."
        />
      }
    <TextInput
        className="form-control"
        placeholder="Enter Name of Budget Category"
        onChange={onChange}
        value={budget.category}
        name="budgetCategory"
      />
    {errors.budgetCategory != "" && generateValidationError(errors.budgetCategory)}
      <div className="form-group input-group">
        <span className="input-group-addon"><i className="fa fa-usd"></i></span>
        <input
          className="form-control"
          placeholder="Monthly Budget Cost"
          onChange={onChange}
          value={budget.cost}
          name="budgetCost"
        />
      </div>
    {errors.budgetCost != "" && generateValidationError(errors.budgetCost)}
      <select
        className="form-control"
        onChange={onChange}
        value={budget.date}
        name="budgetDate"
      >
        <option>Select Day of Month Budget Item is Due</option>
          {renderDays()}
      </select>
    {errors.budgetDate != "" && generateValidationError(errors.budgetDate)}
      <br/>
      {(!errorsInForm(errors)) &&
        <button className="btn btn-primary" type="submit" onClick={() => onSave(budget)}>Add Budget</button>
      }
      {(errorsInForm(errors)) &&
        <button className="btn btn-primary" type="submit" disabled>Fix Form Errors</button>
      }
      </form>
    </div>
  );
};
AddBudgetForm.propTypes = {
  budget: PropTypes.object,
  onChange: PropTypes.func,
  onSave: PropTypes.func,
  errors: PropTypes.object
};
export default AddBudgetForm;

从文档中看,.simulate() 方法仅影响您正在模拟的事件的事件道具。在这种情况下,您传递的合成事件参数将仅提供给您的onChange()函数。实际value道具不受影响。

要确认,只需更新您的自定义onChange()处理程序以console.log提供给它的事件对象,例如

let props = {
    budget: {}, errors: {},
    onChange: (event) => { console.log(event); },
    onSave: () => {}
};

另一个问题是,此模拟不会发生正常的事件冒泡 - 确保直接在要触发事件的节点上运行.simulate()方法。

重构的添加预算窗体注意:这些只是小建议,不一定是唯一正确的方法。

import React, { Component, PropTypes } from 'react';
import Alert from '../common/Alert';
import TextInput from '../common/TextInput';
const renderDays = () => Array(31).fill().map( 
    (_, i = 1) => <option key={i+1}>{i+1}</option> 
);
/**
 * Returns true if a key has a non-null value.
 * @param  {Object} errors - Errors object
 * @return {Boolean} Is there an error?
 */
const errorsInForm = errors => 
    Object.keys(errors).reduce( (hasError, item) => hasError || item != null, false);
const generateValidationError = error => <span style={{color: "red"}}>{error}</span>;
const AddBudgetForm = ({ budget, onChange, onSave, errors = {} }) => (
  <div name="AddBudgetForm">
    <form>
    { ! errorsInForm(errors)
      ? (
      <Alert
        name="add-budget-alert"
        alertType = "alert alert-info"
        fontAwesomeIcon = "fa fa-info"
        alertDescription = " Adding a budget is simple. Add a category such as groceries
        , allocate $200.00 per month and the day you'd like the budget to reset."
      />)
      : (
      <Alert
        name="add-budget-alert"
        alertType = "alert alert-danger"
        fontAwesomeIcon = "fa fa-warning"
        alertDescription = " There are problems with the form submission. Ensure all values in the form are valid."
      />
      )
    }
  <TextInput
      className="form-control"
      placeholder="Enter Name of Budget Category"
      onChange={onChange}
      value={budget.category}
      name="budgetCategory"
    />
  { errors.budgetCategory != "" && 
    generateValidationError(errors.budgetCategory)
  }
    <div className="form-group input-group">
      <span className="input-group-addon"><i className="fa fa-usd"></i></span>
      <input
        className="form-control"
        placeholder="Monthly Budget Cost"
        onChange={onChange}
        value={budget.cost}
        name="budgetCost"
      />
    </div>
  { errors.budgetCost != "" && 
    generateValidationError(errors.budgetCost) 
  }
    <select
      className="form-control"
      onChange={onChange}
      value={budget.date}
      name="budgetDate"
    >
      <option>Select Day of Month Budget Item is Due</option>
        { renderDays() }
    </select>
  { errors.budgetDate != "" && 
    generateValidationError(errors.budgetDate)
  }
    <br/>
    { ! errorsInForm(errors) 
      ? <button className="btn btn-primary" type="submit" onClick={() => onSave(budget)}>Add Budget</button>
      : <button className="btn btn-primary" type="submit" disabled>Fix Form Errors</button>
    }
    </form>
  </div>
);
AddBudgetForm.propTypes = {
  budget: PropTypes.object,
  onChange: PropTypes.func,
  onSave: PropTypes.func,
  errors: PropTypes.object
};
export default AddBudgetForm;

您正在使用一个选择器,该选择器以正确的方式wrapper.find('[name="budgetCategory"]') 的实际 DOM 元素。我假设在TextInput内部你有一个获得相同name的输入。为什么不直接选择TextInput并调用其道具,例如:

wrapper.find('TextInput').prop('onChange')(<some value here>)

最新更新