Input not being updated with simulate change when using Enzyme and React - reactjs

I have a component with an input like this:
const myComponent = () => {
return (
<h2>My component</h2>
<input type="text" value="initial"/>
)
}
export default MyComponent;
I am trying to test value change in this component using Enzyme and Jest like below.
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from '../src/MyComponent';
describe('MyComponent', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<MyComponent />);
});
it('changes the input', () => {
wrapper.find('input').simulate('change', {target: {value: 'new value' }});
expect(wrapper.find('input').prop('value')).toBe('new value');
});
});
The problem is that the value is still ''. I have tried to do wapper.update() or wrapper.setProps({}) but the value does not change. What's wrong ??

The problem was that I wasn't changing the value. My component should de like the following code:
import {React, useState} from 'react';
const myComponent = () => {
const [value, setValue[ = useState('');
return (
<h2>My component</h2>
<input type="text" value={value} />
)
}
export default MyComponent;

Related

Simulate Is not working without state in react js

This is my functional Component.
const InputText = (props: Props) => {
return (
<div>
<StyledInput type="text" placeholder={props.placeholder} />
<br></br>
</div>
);
};
export default InputText;
and this is my test cases.
enter code here
const wrap = (props: Props) => shallow(<InputText {...props} />);
it("input text change", () => {
// const wrap = (props: Props) => mount(<StyledInput {...props} />);
const wrapper = wrap({ placeholder: "UserName" });
const usernameInput = wrapper.find("input");
usernameInput.simulate("change", { target: { value: "umesh#hcl.com" } });
expect(usernameInput.text()).toEqual("umesh#hcl.com");
});
So this test case failed with error:
Expected "Umesh#hcl.com" and recevide:"";
How can I resolve this?
Check this one
App.test.js
import React from "react";
import { shallow, configure } from "enzyme";
import Input from "./App";
import Adapter from 'enzyme-adapter-react-16';
configure({adapter: new Adapter()});
describe("Input Component", () => {
it("should trigger the onchange", () => {
const wrapper = shallow(<Input />);
wrapper
.find("input")
.simulate("change", { target: { value: "on typing" } });
expect(wrapper.find('input').props().value).toBe('on typing')
});
});
App.js
import React, { useState } from "react";
const InputText = props => {
const [inputText, setInput] = useState("");
const onHandleChange = e => {
setInput(e.target.value);
};
return (
<div>
<input
type="text"
value={inputText}
onChange={onHandleChange}
/>
<br />
</div>
);
};
export default InputText;

Enzyme unit testing onChange method using Material UI Components

How would i be able to unit-test onChange method on this component.
Comment.js
import React from "react";
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
const Comment = (props) => (
<div>
<form onSubmit={props.onSubmit}>
<TextField
type="text"
id="outlined-multiline-static"
label="Write A Comment"
multiline
name="comment_body"
value={props.commentBody}
rows="10"
fullWidth
margin="normal"
variant="outlined"
onChange={props.commentChange}
/>
{/* <Button type="submit" variant="outlined" component="span" color="primary">
Post A Comment
</Button> */}
<button type="submit" variant="outlined" component="span" color="primary">
Write a Comment
</button>
</form>
</div>
)
export default Comment;
This is my attempt to unit test the onChange component, getting a
Method “simulate” is meant to be run on 1 node. 0 found instead
around this line
const component = shallow(<Comment commentChange={onChangeMock} commentBody={'test'} />)
component.find('input').simulate('change');
Comment.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import { shallow } from 'enzyme';
import Comment from './Comment';
describe('Should render <Comment/> component', () => {
it('Should render form', () => {
const wrapper = shallow(<Comment/>)
// wrapper.find('Form').at(0)
expect(wrapper.find("form")).toHaveLength(1); // checks if there is a form.
})
it('Should render button', () => {
const wrapper = shallow(<Comment/>)
expect(wrapper.find('button')).toHaveLength(1);
})
it('should check for onChange method', () => {
// const wrapper = shallow(<Comment onChange={}/>)
const onChangeMock = jest.fn();
// const event = {
// preventDefualt(){},
// target: {
// value: 'testing'
// }
// }
const component = shallow(<Comment commentChange={onChangeMock} commentBody={'test'} />)
component.find('input').simulate('change');
expect(onChangeMock).toBeCalledWith('test')
})
})
The Comment component is being passed in another component like this:
ImageContainer.js
state = {
isComment: false,
comment_body: ""
}
handleCommentChange = (e) => {
this.setState({
comment_body: e.target.value
})
}
commentSubmit = (event, id) => {
event.preventDefault();
console.log(this.state.comment_body); // doesn't get console.log
// note that commentBody is being used for the req.body as well so its called by req.body.commentBody
const commentBody = this.state.comment_body
const data = {
commentBody,
id
}
this.props.postComment(data);
this.setState({
comment_body: ''
})
}
<Comment onSubmit={(e) => this.commentSubmit(e, img.id)}
commentBody={this.state.comment_body }
commentChange={this.handleCommentChange}/>
The reason you are having the error is because when you call component.find('input') it returns an array of matched components, so what you want to do is
component.find('input').at(0).simulate('change')
However, there is another way you can test this, which is my preferred method.
component.find('input').at(0).props().onChange()
Below is the correct way to do the test with both methods
import React from "react";
import Enzyme, { shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import Comment from "./Comment";
import TextField from "#material-ui/core/TextField";
Enzyme.configure({ adapter: new Adapter() });
describe("Should render <Comment/> component", () => {
it("should check for onChange method (1)", () => {
// const wrapper = shallow(<Comment onChange={}/>)
const onChangeMock = jest.fn();
const component = shallow(
<Comment commentChange={onChangeMock} commentBody={"test"} />
);
component
.find(TextField)
.at(0)
.simulate("change", "test");
expect(onChangeMock).toBeCalledWith("test");
});
it("should check for onChange method (2)", () => {
// const wrapper = shallow(<Comment onChange={}/>)
const onChangeMock = jest.fn();
const component = shallow(
<Comment commentChange={onChangeMock} commentBody={"test"} />
);
component
.find(TextField)
.at(0)
.props()
.onChange();
expect(onChangeMock).toBeCalled();
});
});
For this particular test it will be better if you just use toBeCalled rather than toBeCalledWith. There is no need to test the value it is called with.

Testing react-final-form using react-testing-library

I'm trying to use react-testing-library to test react-final-form. It works with click-events, like changing a checkbox, but I can't get it working with change-events.
Below is an example using jest as a test runner:
TestForm.js:
import React from 'react';
import { Form, Field } from 'react-final-form';
const TestForm = () => (
<Form
initialValues={{ testInput: 'initial value', testCheckbox: false }}
onSubmit={() => null}
render={({ values, initialValues }) => (
<>
{console.log('VALUES', values)}
<label>
Checkbox label
<Field name="testCheckbox" component="input" type="checkbox"/>
</label>
<Field name="testInput" component="input" placeholder="placeholder" />
{values.testCheckbox !== initialValues.testCheckbox && <div>Checkbox has changed</div>}
{values.testInput !== initialValues.testInput && <div>Input has changed</div>}
</>
)}
/>
);
export default TestForm;
test.js:
import React from 'react';
import { cleanup, fireEvent, render, waitForElement } from 'react-testing-library';
import TestForm from './TestForm';
afterEach(cleanup);
describe('TestForm', () => {
it('Change checkbox', async () => {
const { getByLabelText, getByText } = render(<TestForm />);
const checkboxNode = getByLabelText('Checkbox label');
fireEvent.click(checkboxNode);
await waitForElement(() => getByText('Checkbox has changed'));
});
it('Change input', async () => {
const { getByPlaceholderText, getByText } = render(<TestForm />);
const inputNode = getByPlaceholderText('placeholder');
fireEvent.change(inputNode, { target: { value: 'new value' } });
await waitForElement(() => getByText('Input has changed'));
});
});
I run this using npx jest test.js and the first test passes but not the second.
The crucial part that doesn't seem to work is
fireEvent.change(inputNode, { target: { value: 'new value' } });
Any suggestions?

Jest How to test react form submission?

Consider the following component:
import React, { Component } from "react";
import ImageUpload from "./ImageUpload/ImageUpload";
import axios from "axios";
class Dashboard extends Component {
state = {
fileName: ""
};
onFormSubmit = e => {
e.preventDefault();
const { group, country } = e.target;
axios.post("/api/dashboard", {
name: group.value,
country: country.value,
image: this.state.fileName
});
//TODO redirect the user
};
onFileNameChange = name => {
this.setState({ fileName: name });
};
render() {
return (
<div>
<form onSubmit={this.onFormSubmit}>
<input type="text" name="group" placeholder="Group Name" />
<input type="text" name="country" placeholder="Country" />
<ImageUpload
fileName={this.state.fileName}
onFileNameChange={this.onFileNameChange}
/>
<button type="submit">Add Group</button>
</form>
</div>
);
}
}
export default Dashboard;
I am trying to fake the submission of a form and test that when onFormSubmit is being called. I make onFormSubmit a spy function. But, it is not being called at all.
import React from "react";
import Dashboard from "components/admin/Dashboard/Dashboard";
import { shallow, render } from "enzyme";
describe("The Dashboard component", () => {
it("should not regress", () => {
const wrapper = render(<Dashboard />);
expect(wrapper).toMatchSnapshot();
});
it("should submit the form and send the group to server", () => {
const wrapper = shallow(<Dashboard />);
const preventDefault = jest.fn();
const event = {
preventDefault,
target: {
group: "Samrat",
country: "Nepal"
}
};
wrapper.instance().onFormSubmit = jest.fn();
wrapper.update();
wrapper.find("form").simulate("submit", event);
expect(wrapper.instance().onFormSubmit).toHaveBeenCalledWith(event);
});
});

React component test with enzyme

I have a component like this:
component.js
import React from "react";
import PropTypes from "prop-types";
const Test = ({ text }) => (
<div>
{text.split("\n").map((item, key) => {
return (
<span key={key}>
{item}
<br />
</span>
);
})}
</div>
);
Test.propTypes = {
text: PropTypes.string.isRequired
};
export default Test;
How do i write component test for this react component using enzyme? I am new to react and enzyme. Any help will really appreciable.
This could be a test using mocha:
import {shallow} from 'enzyme'
import assert from 'assert'
import Test from './Test'
describe('component Test', () => {
it('should show a span for each line of "text" prop', () => {
const text = `foo
bar
`
const wrapper = shallow(<Test text={text} />)
const spans = wrapper.find('span')
assert.equal(spans.length, 2)
assert.equal(spans.at(0).text(), 'foo')
assert.equal(spans.at(1).text(). 'bar')
})
it('should throw if "text" prop is not provided', () => {
assert.throws(() => {
shallow(<Text />)
})
})
})
Here is shamelessly taken example of testing dom using enzyme + jest (from jest web site):
// __tests__/CheckboxWithLabel-test.js
import React from 'react';
import {shallow} from 'enzyme';
import CheckboxWithLabel from '../CheckboxWithLabel';
test('CheckboxWithLabel changes the text after click', () => {
// Render a checkbox with label in the document
const checkbox = shallow(
<CheckboxWithLabel labelOn="On" labelOff="Off" />
);
expect(checkbox.text()).toEqual('Off');
checkbox.find('input').simulate('change');
expect(checkbox.text()).toEqual('On');
});
I recommend you to go though the link I gave - it contains nice examples of testing react components using Jest + Enzyme.

Resources