New to react-router and having issues with Jest/Enzyme tests failing due to react-routers history prop.
The idea:
On submit of the form component call handleSubmit.
handleSubmit calls validate to do some simple validation on the form.
If validated history.push('/new-url-to-navigate-to')
Else if not validated pushes error message to state.
The idea works when running the project - a valid form submit navigates to the /sent
component, as expected.
So far so good.
The Issue
My issue comes from my jest/enzyme unit test to test whether the component renders an error message when the validation fails. The test code:
import React from 'react'
import { mount } from 'enzyme'
import { MemoryRouter } from 'react-router-dom'
import Form from '../Form'
describe('<Form />', () => {
it('validates invalid form', () => {
const component = mount(
<MemoryRouter
initialEntries={["/", "/form", "/saved"]}
initialIndex={1}
>
<Form />
</MemoryRouter>
)
const input = component.find('input')
input.value = ""
const form = component.find('form')
form.simulate('submit', { preventDefault: () => {},
target: {
routingTextbox: input
}});
expect(component.find('h3').length).toBe(1)
})
})
Which fails with:
<Form /> › validates invalid form
TypeError: Cannot read property 'push' of undefined
48 |
49 | if (isValid) {
> 50 | history.push('/sent')
The error prevents the test from running and fails. If I remove/comment the history.push('/sent') line, the test passes, but I obviously need this line to navigate to the next page (as I say this works when running the project - it is just the test that is failing. I seem to not have access to the history prop in my component. Any help on how to move forward with this would be greatly appreciated.
Form component for reference
I don't think the issue is in here, since it's working perfectly when running the project, but would be happy to be proved wrong if I can get this test working!
// Form component
import React, { useState } from 'react';
const Form = ({ history }) => {
const [state, setState] = useState({
error: {
isValid: true,
message: ''
}
})
const handleClick = () => {
history.goBack()
}
const renderError = () => {
if (state.error.isValid === false) {
return(
<div>
<h3>{state.error.message}</h3>
</div>
)
}
return null
}
const validate = (value) => {
if (value === "") {
setState({
error: {
isValid: false,
message: 'Please enter a value in the textbox'
}
})
return false
}
return true
}
const handleSubmit = (e) => {
e.preventDefault()
const isValid = validate(e.target.routingTextbox.value)
if (isValid) {
history.push('/sent')
} else {
console.log('textbox is empty')
}
}
return (
<form onSubmit={handleSubmit}>
<input type="text" name="routingTextbox" />
<button type="submit">Submit</button>
<button type="button" onClick={handleClick}>Go Back</button>
{renderError()}
</form>
)
}
export default Form
Router for reference
const App = () => (
<Router>
<Switch>
<Route path="/" exact component={Index} />
<Route path="/form" component={Form} />
<Route path="/sent" component={Sent} />
</Switch>
</Router>
)
export default App;