#7 Add integration tests for sign-in process

Missing in this commit:
* take care of router stuff
This commit is contained in:
Christoph Lienhard 2020-12-27 16:25:10 +01:00
parent 6f277ef21f
commit 331e511368
Signed by: christoph.lienhard
GPG key ID: 6B98870DDC270884
3 changed files with 126 additions and 13 deletions

View file

@ -1,9 +0,0 @@
import React from 'react';
import { render } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View file

@ -4,10 +4,10 @@ import CssBaseline from '@material-ui/core/CssBaseline';
import TextField from '@material-ui/core/TextField';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import {Link, useHistory} from 'react-router-dom';
import Grid from '@material-ui/core/Grid';
import Box from '@material-ui/core/Box';
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
import {Link, useHistory} from 'react-router-dom';
import Typography from '@material-ui/core/Typography';
import {makeStyles} from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
@ -42,8 +42,11 @@ const useStyles = makeStyles((theme) => ({
export default function SignIn() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [login, {loading, error, data}] = useMutation<LoginMutationResponse, LoginMutationVariables>(loginMutation);
const [login, {loading, error, data}] = useMutation<LoginMutationResponse, LoginMutationVariables>(
loginMutation
);
const history = useHistory();
const classes = useStyles();
if (data && data.authenticate.jwtToken) {
@ -109,7 +112,7 @@ export default function SignIn() {
<p className={classes.error}>
{error
? `Error while trying to log in: ${error.message}`
: data && !data.authenticate.jwtToken ? "Wrong username or password" : ""}
: !data?.authenticate.jwtToken ? "Wrong username or password" : ""}
</p>
<Grid container>
<Grid item xs>
@ -133,7 +136,7 @@ export default function SignIn() {
);
}
const loginMutation = gql`
export const loginMutation = gql`
mutation Login($email: String!, $password: String!) {
authenticate(input: {email: $email, password: $password}) {
jwtToken

View file

@ -0,0 +1,119 @@
import React from 'react';
import SignIn, {loginMutation, LoginMutationResponse} from "../components/SignIn";
import {fireEvent, render, screen, waitFor} from '@testing-library/react'
import {MockedProvider, MockedResponse} from '@apollo/client/testing';
import {MemoryRouter} from 'react-router-dom';
const mockHistoryReplace = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useHistory: () => ({
replace: mockHistoryReplace,
}),
}));
const mocks: Array<MockedResponse<LoginMutationResponse>> = [
{
request: {
query: loginMutation,
variables: {
email: "test@email.com",
password: "password",
}
},
result: {
data: {
authenticate: {
jwtToken: "123"
}
}
},
},
{
request: {
query: loginMutation,
variables: {
email: "test@email.com",
password: "wrong-password",
}
},
result: {
data: {
authenticate: {
jwtToken: null
}
}
},
}
]
describe('SignIn page', () => {
beforeEach(() => mockHistoryReplace.mockReset())
test('initial state', () => {
render(<MockedProvider mocks={mocks}><MemoryRouter><SignIn/></MemoryRouter></MockedProvider>);
// it renders empty email and passsword fields
const emailField = screen.getByRole('textbox', {name: 'Email Address'});
expect(emailField).toHaveValue('');
const passwordField = screen.getByLabelText(/Password/);
expect(passwordField).toHaveValue('');
// it renders enabled submit button
const button = screen.getByRole('button');
expect(button).not.toBeDisabled();
expect(button).toHaveTextContent('Sign In');
expect(mockHistoryReplace).not.toHaveBeenCalled();
});
test('successful login', async () => {
render(<MockedProvider mocks={mocks}><MemoryRouter><SignIn/></MemoryRouter></MockedProvider>);
const emailField = screen.getByRole('textbox', {name: 'Email Address'});
const passwordField = screen.getByLabelText(/Password/);
const button = screen.getByRole('button');
// fill out and submit form
fireEvent.change(emailField, {target: {value: 'test@email.com'}});
fireEvent.change(passwordField, {target: {value: 'password'}});
fireEvent.click(button);
await waitFor(() => {
// it hides form elements
expect(button).not.toBeInTheDocument();
expect(emailField).not.toBeInTheDocument();
expect(passwordField).not.toBeInTheDocument();
// it displays success text and email address
const loggedInText = screen.getByText(/Success/);
expect(loggedInText).toBeInTheDocument();
expect(mockHistoryReplace).toHaveBeenCalledWith("/");
});
});
test('error login', async () => {
render(<MockedProvider mocks={mocks}><MemoryRouter><SignIn/></MemoryRouter></MockedProvider>);
const emailField = screen.getByRole('textbox', {name: 'Email Address'});
const passwordField = screen.getByLabelText(/Password/);
const button = screen.getByRole('button');
// fill out and submit form
fireEvent.change(emailField, {target: {value: 'test@email.com'}});
fireEvent.change(passwordField, {target: {value: 'wrong-password'}});
fireEvent.click(button);
await waitFor(() => {
// it resets button
expect(button).not.toBeDisabled();
expect(button).toHaveTextContent('Sign In');
// it displays error text
const errorText = screen.getByText(/Wrong username or password/);
expect(errorText).toBeInTheDocument();
expect(mockHistoryReplace).not.toHaveBeenCalled();
});
});
});