I have a simple form with just one text field. I have used react material ui library along with formik for validations and verification. I'm unable to get the textfield within the form by using shallow method of enzyme. Not sure what I'm doing wrong.
declarationForm.js
import React, { useState, useEffect } from 'react';
import * as Yup from 'yup';
import { Formik } from 'formik';
import { useNavigate, Prompt } from "react-router-dom";
import { Box, Button, Card, CardContent, CardHeader, Divider, Grid, TextField } from '@material-ui/core';
import { get_declarations_details, put_declarations_details } from './../../utils/service';
const DeclarationsForm = () => {
const [ initialData, setInitialData ] = useState({ declarations:'' });
useEffect(()=>{
get_data();
},[]);
let navigate = useNavigate();
const get_data = async() =>{
try {
const result = await get_declarations_details();
if(result){
setInitialData({
...initialData,
...result,
});
}
} catch (error) {
console.log(error);
}
}
const put_data = async(data) =>{
try {
const result = await put_declarations_details(data);
if(result){
setInitialData({
...initialData,
...result,
});
}
} catch (error) {
console.log(error);
}
}
return (
<Formik
initialValues={initialData}
enableReinitialize={true}
validationSchema={
Yup.object().shape({
declarations: Yup.string().max(255).required('Declarations is required'),
})
}
onSubmit={(values) => {
if(JSON.stringify(initialData) !== JSON.stringify(values)){
put_data(values);
}
navigate(`/summary`, { replace: true })
}}
>
{({
errors,
handleBlur,
handleChange,
handleSubmit,
isSubmitting,
touched,
isValid,
values
}) => (
<form onSubmit={handleSubmit}>
<Card>
<Prompt
when={!isValid}
message="Are you sure you want to proceed without saving?"
/>
<CardHeader
subheader="The information can be edited"
title="Declarations"
/>
<Divider />
<CardContent>
<Grid
container
spacing={3}
>
<Grid
item
md={6}
xs={12}
>
<TextField
fullWidth
error={Boolean(touched.declarations && errors.declarations)}
helperText={touched.declarations && errors.declarations}
label="Declarations"
name="declarations"
handleBlur={handleBlur}
onChange={handleChange}
required
value={values.declarations}
variant="outlined"
/>
</Grid>
</Grid>
</CardContent>
<Divider />
<Box
display="flex"
justifyContent="flex-end"
p={2}
>
<Button
color="primary"
variant="contained"
disabled={isSubmitting}
onClick={handleSubmit}
>
Continue
</Button>
</Box>
</Card>
</form>
)}
</Formik>
);
};
export default DeclarationsForm;
My test file is as below
declarationForm.test.js
import { createShallow } from '@material-ui/core/test-utils';
import React from 'react';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import DeclarationsForm from './declarationsForm';
import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles';
import { TextField } from '@material-ui/core';
configure({ adapter: new Adapter() });
describe('<DeclarationsForm />', () => {
let shallow, wrapper;
beforeAll(() => { // This is Mocha; in Jest, use beforeAll
shallow = createShallow();
});
beforeEach(() => {
wrapper = shallow(<MuiThemeProvider><DeclarationsForm /></MuiThemeProvider>);
});
it('should work', () => {
console.log(wrapper.find(TextField).debug());
expect(wrapper.find(TextField)).toHaveLength(1);
});
});
When I run the test below is the result
FAIL src/views/declarations/declarationsForm.test.js
● Console
console.error node_modules/prop-types/checkPropTypes.js:20
Warning: Failed prop type: The prop `theme` is marked as required in `ThemeProvider`, but its value is `undefined`.
in ThemeProvider (at declarationsForm.test.js:19)
console.log src/views/declarations/declarationsForm.test.js:23
● <DeclarationsForm /> › should work
expect(received).toHaveLength(expected)
Expected length: 1
Received length: 0
Received object: {}
22 |
23 | console.log(wrapper.find(TextField).debug());
> 24 | expect(wrapper.find(TextField)).toHaveLength(1);
| ^
25 | });
26 | });
at Object.<anonymous> (src/views/declarations/declarationsForm.test.js:24:37)
wrapper is unable to find text field or form.
How to debug this? What is the right approach to write test when we have also used useNavigate method within the component?
theme
prop toMuiThemeProvider
in your test. I ditched Enzyme a long time ago, but perhaps if you did a fullmount
versusshallow
, I think theshallow
mounting treats children components differently and doesn't fully render them. – Drew Reese