I have a simple "Edit User" component which contains a form with a "First Name" field. When the component first renders, that field is blank until an API request for the user's data is completed. Once the data is fetched, the state gets updated and the component re-renders, this time with the "First Name" field populated. (To be clear, no user interaction is required for this to happen.)
My test, which expects the "First Name" field to be correctly populated, is currently failing because it's only testing the initial render of my component, before the user info can be fetched.
What's an efficient way to test this behavior ie wait until the (mocked) request is completed before any assertions are made?
FWIW, I'm using React 16.12.0.
Here's the abbreviated component:
import React, { useState, useEffect } from 'react'
import axios from 'axios'
const EditUser = (props) => {
const [user, setUser] = useState({
fname: "",
lname: ""
})
const fetchUser = async () => {
await axios.get(`/api/users/${props.userId}`)
.then(response => {
const data = response.data
const user = {
fname: data.attributes.fname,
lname: data.attributes.lname
}
setUser(user)
})
.catch(error => console.log(error))
}
useEffect(() => {
fetchUser()
}, [])
return (
<div>
<h2>Edit User</h2>
<form>
<div className="form-group">
<label>First Name</label>
<input
name="fname"
value={user.fname}
/>
</div>
</form>
</div>
)
}
export default EditUser
And the test:
import React from 'react'
import { mount } from 'enzyme'
import { act } from 'react-dom/test-utils'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
import EditUser from 'packs/editUser'
describe('editUser', () => {
let wrapper
const axiosMock = new MockAdapter(axios)
axiosMock.onGet('/api/users/5').reply(200, {
id: 5,
attributes: {
fname: 'Bradley',
lname: 'King'
}
})
it('shows the user edit form', async () => {
await act(async () => {
wrapper = await mount(<EditUser userId={5} />)
})
const firstNameInput = wrapper.find('input[name="fname"]')
// the following FAILS because the first name input is blank
// _until_ the user data is fetched and the component is
// re-rendered with field populated
expect(firstNameInput.props().value).toEqual('Bradley')
})
})
Thanks!
Since you are expecting a render to have occurred, you can use the .update()
method of the wrapper
to
Sync the enzyme component tree snapshot with the react component tree. Useful to run before checking the render output if something external may be updating the state of the component somewhere.
it('shows the user edit form', async() => {
await act(async() => {
wrapper = await mount(<EditUser userId={5} />)
})
wrapper.update();
const firstNameInput = wrapper.find('input[name="fname"]')
expect(firstNameInput.props().value).toEqual('Bradley')
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.