Monday, May 20, 2024
162
rated 0 times [  164] [ 2]  / answers: 1 / hits: 34693  / 8 Years ago, tue, january 3, 2017, 12:00:00

I have been trying to unit test a react component that takes in user input. More specifically I'm trying to test the onChange function within the react component. However I can't seem to set the input value, I've tried a few different ways suggested on the internet and none seem to work. Below is the component I'm trying to test.



class Input extends Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
}

handleChange(event) {
/* Check if max length has been set. If max length has been
set make sure the user input is less than max Length, otherwise
return before updating the text string. */
if(this.props.maxLength) {
if(event.target.value.length > this.props.maxLength) {
return;
}
}
this.setState({ value: event.target.value });
}

render () {
const { disabled, label, maxLength, multiline, type, value, ...others} = this.props;
const theme = themeable(others.theme);

let inputClassName = classNames({
input: type !== 'checkbox',
checkbox: type == 'checkbox',
disabled,
multiline,
value,
[`${this.props.className}`]: !!this.props.className
});

return (
<div {...theme(1, 'container')}>
{this.props.label ? <label htmlFor={this.props.htmlFor} {...theme(2, 'label')}>{label}</label> : null}
<input value={this.state.value} {...theme(3, ...inputClassName)} onChange={this.handleChange} type={type} />
</div>
);
}
}


I found this issue: https://github.com/airbnb/enzyme/issues/76 and tried the suggestions towards the bottom, I keep getting either undefined or a blank string. I tried levibuzolic's suggestion of using enzyme's simulate change, which can be seen below. However this just returns AssertionError: expected '' to equal 'abcdefghij'



it('Make sure inputted text is shorter than max length', function() {
const result = mount(<Input maxLength={10}></Input>);
result.find('input').simulate('change', {target: {value: 'abcdefghijk'}});
expect(result.state().value).to.equal(abcdefghij);
});


Then I tried takkyuuplayer's suggestion which is also below. This also fails with AssertionError: expected '' to equal 'abcdefghij'



  it('Make sure inputted text is shorter than max length', function() {
const result = mount(<Input maxLength={10}></Input>);
result.find('input').node.value = 'abcdefghijk';
expect(result.state().value).to.equal(abcdefghij);
});


I found this article: https://medium.com/javascript-inside/testing-in-react-getting-off-the-ground-5f569f3088a#.f4gcjbaak and tried their way which also failed.



  it('Make sure inputted text is shorter than max length', function() {
const result = mount(<Input maxLength={10}></Input>);
let input = result.find('input');
input.get(0).value = 'abcdefghijk';
input.simulate('change');
expect(result.state().value).to.equal(abcdefghij);
});


Finally I tried using the react test utils as suggested by Simulating text entry with reactJs TestUtils, below is the code I tried, however this failed with the error message: TypeError: Cannot read property '__reactInternalInstance$z78dboxwwtrznrmuut6wjc3di' of undefined



  it('Make sure inputted text is shorter than max length', function() {
const result = mount(<Input maxLength={10}></Input>);
let input = result.find('input');
TestUtils.Simulate.change(input, { target: { value: 'abcdefghijk' } });
expect(result.state().value).to.equal(abcdefghij);
});


So how does one simulate user input so they can test the onChange function?


More From » unit-testing

 Answers
8

You seem to have a bug in your Input component. When event.target.value.length > this.props.maxLength you never set the actual state, leaving the state.value as ''. It seems you expected it to have been set to the value, but truncated to maxLength. You'll need to add that yourself:



handleChange(event) {
/* Check if max length has been set. If max length has been
set make sure the user input is less than max Length, otherwise
return before updating the text string. */
if (this.props.maxLength) {
if (event.target.value.length > this.props.maxLength) {
// ** Truncate value to maxLength
this.setState({ value: event.target.value.substr(0, this.props.maxLength) });
return;
}
}
this.setState({ value: event.target.value });
}


... then, the following test works and passes:



it('Make sure inputted text is shorter than max length', () => {
const result = mount(<Input maxLength={10}></Input>);
result.find('input').simulate('change', { target: { value: '1234567890!!!' } });
expect(result.state().value).to.equal(1234567890);
});

[#59474] Sunday, January 1, 2017, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
zariahdiamondz

Total Points: 649
Total Questions: 109
Total Answers: 88

Location: Tajikistan
Member since Thu, Apr 14, 2022
2 Years ago
;