Skip to content

Instantly share code, notes, and snippets.

@einatnielsen
Last active October 17, 2019 13:38
Show Gist options
  • Save einatnielsen/bc6863ec367fef4f2a5fed763ee2b5fb to your computer and use it in GitHub Desktop.
Save einatnielsen/bc6863ec367fef4f2a5fed763ee2b5fb to your computer and use it in GitHub Desktop.
import {mount} from 'enzyme'
import React from 'react'
import Login from '../login'
test('allows the user to login successfully', async () => {
// mock out window.fetch for the test
const fakeUserResponse = {token: 'fake_user_token'}
jest.spyOn(window, 'fetch').mockImplementationOnce(() => {
return Promise.resolve({
json: () => Promise.resolve(fakeUserResponse),
})
})
const wrapper = mount(<Login/>)
// fill out the form
wrapper.find('#usernameInput').simulate('change', {target: {value: 'chuck'})
wrapper.find('#passwordInput').simulate('change', {target: {value: 'norris'})
wrapper.find('button[type=\"submit\"]').simulate('click')
await new Promise(resolve => setImmediate(resolve))
expect(wrapper.find('role=\"alert\"')).toContain('congrats')
expect(window.localStorage.getItem('token')).toEqual(fakeUserResponse.token)
// Implementation detail, shouldn't be tested
expect(wrapper.state('resolved')).toBeTruthy()
})
test('Login implementation details', async () => {
const wrapper = mount(<Login/>)
expect(wrapper.find('#usernameInput').length).toBe(1)
expect(wrapper.find('#passwordInput').length).toBe(1)
})
test('Empty Form', async () => {
// mock out window.fetch for the test
const fakeUserResponse = {token: 'fake_user_token'}
jest.spyOn(window, 'fetch').mockImplementationOnce(() => {
return Promise.reject({
message: 'Error message'
})
})
const wrapper = mount(<Login/>)
// Trigger handleSubmit with empty inputs
wrapper.instance().handleSubmit({target: {elements: {}}})
await new Promise(resolve => setImmediate(resolve))
expect(wrapper.state('error')).not.toBeNull()
})
import React from 'react'
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
resolved: false,
loading: false,
error: null
};
}
handleSubmit = event => {
event.preventDefault();
const { usernameInput, passwordInput } = event.target.elements;
this.setState({ loading: true, resolved: false, error: null });
window
.fetch("/api/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: usernameInput.value,
password: passwordInput.value
})
})
.then(r => r.json())
.then(
user => {
this.setState({ loading: false, resolved: true, error: null });
window.localStorage.setItem("token", user.token);
},
error => {
this.setState({
loading: false,
resolved: false,
error: error.message
});
}
);
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<div>
<label htmlFor="usernameInput">Username</label>
<input id="usernameInput" />
</div>
<div>
<label htmlFor="passwordInput">Password</label>
<input id="passwordInput" type="password" />
</div>
<button type="submit">
Submit{this.state.loading ? "..." : null}
</button>
</form>
{this.state.error ? (
<div role="alert">{this.state.error.message}</div>
) : null}
{this.state.resolved ? (
<div role="alert">Congrats! You're signed in!</div>
) : null}
</div>
);
}
}
export default Login;
import '@testing-library/jest-dom/extend-expect'
import React from 'react'
import {render, fireEvent} from '@testing-library/react'
import Login from '../login'
test('allows the user to login successfully', async () => {
// mock out window.fetch for the test
const fakeUserResponse = {token: 'fake_user_token'}
jest.spyOn(window, 'fetch').mockImplementationOnce(() => {
return Promise.resolve({
json: () => Promise.resolve(fakeUserResponse),
})
})
const {getByLabelText, getByText, findByRole} = render(<Login />)
// fill out the form
fireEvent.change(getByLabelText(/username/i), {target: {value: 'chuck'}})
fireEvent.change(getByLabelText(/password/i), {target: {value: 'norris'}})
fireEvent.click(getByText(/submit/i))
// just like a manual tester, we'll instruct our test to wait for the alert
// to show up before continuing with our assertions.
const alert = await findByRole('alert')
// .toHaveTextContent() comes from jest-dom's assertions
// otherwise you could use expect(alert.textContent).toMatch(/congrats/i)
// but jest-dom will give you better error messages which is why it's recommended
expect(alert).toHaveTextContent(/congrats/i)
expect(window.localStorage.getItem('token')).toEqual(fakeUserResponse.token)
})
test('Empty Form', async () => {
// mock out window.fetch for the test
const fakeUserResponse = {token: 'fake_user_token'}
jest.spyOn(window, 'fetch').mockImplementationOnce(() => {
return Promise.reject({
message: 'Error message'
})
})
const {getByText, findByRole} = render(<Login />)
fireEvent.click(getByText(/submit/i))
const alert = await findByRole('alert')
expect(alert).toHaveTextContent(/Error/i)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment