我正在进行一些基本的表格互动测试
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;
答案 0 :(得分:1)
从docs开始,.simulate()
方法仅影响您正在模拟的事件的事件道具。在这种情况下,您传递的合成事件args将仅提供给您的onChange()
函数。实际的value
道具不受影响。
要确认,只需将自定义onChange()
处理程序更新为console.log
提供给它的事件对象,例如
let props = {
budget: {}, errors: {},
onChange: (event) => { console.log(event); },
onSave: () => {}
};
另一个问题是,此模拟不会发生正常事件冒泡 - 请确保直接在要触发事件的节点上运行.simulate()
方法。
重构的AddBudgetForm 注意:这些只是一些小建议,并不一定是唯一正确的方法。
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;
答案 1 :(得分:0)
您正在使用一个以实际DOM元素为目标wrapper.find('[name="budgetCategory"]')
的选择器。我假设在TextInput
内你有一个输入相同的name
。为什么不直接选择TextInput
并调用其支柱,例如:
wrapper.find('TextInput').prop('onChange')(<some value here>)