How to we simulate a file upload in jest - reactjs

I'm writing a test using jest to test my reactJS components. I need to simulate a file upload in jest to test my reactjs component. Does anyone know how? Here's my code
<div className="add-graphic-card-cta">
<input
ref={inputRef}
className='add-graphic-card-file'
type="file"
accept=".jpg,.jpeg,.png,image/jpeg,image/png"
onChange={this._handleChooseGraphicChange.bind(this)}
onDrop={(e) => {
e.preventDefault();
return false;
}}
/>
<Button
className="add-graphic-card-button"
label={this.props.intl.formatMessage({ id: 'ccl-graphic-verb-add' })}
variant="cta"
onClick={this.onFileUpload.bind(this, inputRef)} />
</div>
Here's the test
it('upload a file', () => {
const fn = jest.fn();
const header = shallowWithIntl(<LibraryManagerAddGraphicCard onClick={fn} />).dive();
header.find('.add-graphic-card-button').simulate('click', {
preventDefault: jest.fn(),
stopPropagation: jest.fn()
});

I have not actually tried this one out, but I suppose you can simulate the onChange event to mock the file upload event:
header.find('.add-graphic-card-file').simulate('change', {
target: {
files: ['file.jpg'],
},
});
This should cause the _handleChooseGraphicChange method to be triggered.

Related

Crash in Test React Jest when testing an input with onFocus to change an attibute

My Component have a field like this:
<Form.Label>E-mail</Form.Label>
<Form.Control
data-testid="inputemail"
type="email"
onFocus={() => setAttribute(false)}
readOnly={attribute}
placeholder="Enter e-mail"
/>
</Form.Group>
And I tried to pass this test:
it("should change 'Email' input value", async () => {
render(<LoginPage />);
const textVariable = "";
const inputemail = screen.getByTestId("inputemail");
inputemail.focus();
fireEvent.input(inputemail, { target: { value: textVariable } });
expect(inputemail).toHaveFocus(); //passing now
await waitFor(() => {
expect(inputemail.innerHTML).toBe(textVariable);
});
});
Test passed ok, but I get this warning:
What can I do? What is the issue, I don't understand.
The act error is saying that you are trying to access the component when it is not in stable state. Your onFocus is changing internal state of the component so the test needs to wait until it is rerendered.
Try to do the following, replace this:
inputemail.focus();
fireEvent.input(inputemail, { target: { value: textVariable } });
expect(inputemail).toHaveFocus(); //passing now
with this:
inputemail.focus();
await waitFor(() => expect(inputemail).toHaveFocus());
fireEvent.input(inputemail, { target: { value: textVariable } });
or instead of using fireEvent use the #testing-library/user-event library which should focus the field when using the type method.
await userEvent.type(inputemail, textVariable);
Just remember that user event lib API is async.

Test useRef's currents' properties using jest-enzyme

I am trying to test a hidden file inputs click using Jest-enzyme, for the following component.
const UploadField = ({handleFileUpload}) => {
const hiddenFileInputRef = React.useRef(null);
const handleChange = (event) => {
handleFileUpload(event.target.files[0]);
};
const handleClick = () => {
hiddenFileInputRef.current.click();
};
return (
<>
<input
type="file"
ref={hiddenFileInputRef}
onChange={handleChange}
style={{display: 'none'}}
/>
<div
onClick={handleClick}
className="upload-button-container">
upload file
</div>
</>
);
};
i tried the following test :
it('should call handle click of hidden fileinput on click of div', () => {
const useRefSpy = jest
.spyOn(React, 'useRef')
.mockReturnValueOnce({current: {click: jest.fn()}});
let divWrapper = wrapper.find(
'.upload-button-container'
);
divWrapper.simulate('click');
expect(useRefSpy).toBeCalledTimes(1);
});
It gives an error "TypeError: Cannot read property 'click' of null" . what am i doing wrong here?
Try to check if you were able find the right div by logging wrapperDiv.html() or debugging
I think you might have to pass the event like in this post. Simulating a Div Click on Enzyme and React

How to test if some element was enabled/disabled correctly after click a Checkbox?

I'm trying to test a component that have a <Switch/> (using Material-UI) and a <TextField/>. When user clicks in this Switch, it makes another field (<TextField/>) enable/disabled. The code works well, but my test using JEST always fails.
...
export function MyComponent(): JSX.Element{
const [enableExpiresOn, setEnableExpiresOn] = useState(false);
...
function handleAccountExpiresOn(e: React.ChangeEvent<HTMLInputElement>) {
setEnableExpiresOn(e.target.checked);
}
return (
<form ...>
...
<div>
<FormControlLabel
control={
<Switch
id="account-expires"
onChange={handleAccountExpiresOn}
name="account-expires"
color="primary"
checked={enableExpiresOn}
/>
}
label={t("Account Expires On")}
/>
</div>
<div>
<TextField
id="account-expires-on"
label={t("Account Expires On")}
type="datetime-local"
variant="outlined"
required={enableExpiresOn}
InputLabelProps={{
shrink: true,
}}
disabled={!enableExpiresOn}
/>
</div>
...
</form>
);
}
And in my JEST test file, I have the follow (as you can see, I'm trying to simulate a click in the Switcher):
describe("Should render correctly", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(<MyComponent />);
});
...
fit("Should enable Account Expires On when switcher is on/checked", async () => {
wrapper.find("#account-expires").at(0).simulate("click");
expect(
wrapper.find("#account-expires-on").get(0).props.disabled
).toEqual(false);
});
However, Jest gives me an error in this expectation, saying that it have received true instead false.
I tried to put a setTimeout around the expectation, hoping that it would solve the problem because maybe we need to wait for the click to have effect, but it doesn't work.
I'm newer with JEST and React Hooks. So, I don't know if it is the best way to test what this behaviour or there is a better way.
Used Technologies
React Hooks
NextJS
Material UI
TypeScript
Jest
Enzyme
useState is async, jest check assertion before element get disabled.
Can try:
describe("Should render correctly", () => {
let wrapper;
beforeAll(() => {
wrapper = mount(<MyComponent />);
});
...
fit("Should enable Account Expires On when switcher is on/checked", () => {
jest.useFakeTimers()
wrapper.find("#account-expires").at(0).simulate("click");
jest.runAllTimers()
// or possibly
// await new Promise(resolve => setTimeout(resolve, 0))
expect(
wrapper.find("#account-expires-on").get(0).props.disabled
).toEqual(false);
});
And can google it
UPD
Can try to simulate onChange event or wrapper.find("#account-expires").at(0).props().onChange(); from here
Similar troubles with testing-library https://github.com/mui-org/material-ui/issues/17697

Testing Formik using enzyme and jest in react

My Formik page:
const IssueForm =({values,errors,touched,isSubmitting})=>{
const [modified,setModified] = useState(false);
const handleModified = () => setModified(true);
const handleSubmit = () => setModified(false);
return(
<div><br></br><br></br><br></br><br></br>
<h1>Add Issue</h1><br></br>
<Form>
<div>
<label>Description: </label>
<Field width="100px" type="text" name="issueDescription" placeholder="issuedescription" onInput={handleModified}/>
{touched.issueDescription && errors.issueDescription&&<span style={{color:'red'}}>{errors.issueDescription}</span>}
</div><div><br></br>
<button type ="submit" disabled={isSubmitting} onClick={handleSubmit}>Submit</button>
</Form>
</div>
)
};
I have mentioned one field .like this I have so many fields.
when I used normal form I generated test cases successfully as below.
describe('Test UserForm using Shallow rendering', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<UserForm/>);
});
it('has 1 text input elements', () => {
expect(wrapper.find('input').length).toEqual(1);
})
it('should allow to type in issuedescription input field', () => {
wrapper.find('input#issueDescription').simulate('change', {
target: {value: 'Sachin'}
});
wrapper.update();
expect(wrapper.find('input#issueDescription').prop('value')).toEqual('Sachin');
})
});
when I changed my normal from to formik I executed the same test cases in formik I am getting error.
for first case :
expect(received).toEqual(expected) // deep equality
Expected: 1
Received: 0
for second case:
Method “simulate” is meant to be run on 1 node. 0 found instead.
I need to run this two cases for formik page .Iam new to react .can anyone help??

React mock submit form function using Jest and Enzyme

I'm trying to create a "simple" test to check if the onSubmit function of the form has been added / not removed from the component.
Form component:
<form onSubmit={SubmitForm} data-test="submit-new-product-form" >
<TextField type="text" ref={enteredNameRef} className="text-field" label="Name" value={enteredName} onChange={event => { handleChange('enteredName', setEnteredName, event.target.value) } } data-test="input-entered-name" /></form>
Test example:
test('should call submitNewProduct function upon form submission', () => {
let submitNewProduct = jest.fn(); //This is the mock I'm trying to put to check if it was called
let wrapper = shallow(<AddNewProduct />);
let form = wrapper.find("[data-test='submit-new-product-form']");
//This is where things don't make sense to me. Above I have the form component and I need to assign the
//submitNewProduct mock function to its onSubmit prop. But I don't know how.
form.simulate('submit', { preventDefault: () => console.log('preventDefault') });
expect(submitNewProduct).toHaveBeenCalled();
});
Any ideas please?

Resources