Skip to content

Commit

Permalink
Merge pull request #32 from ECE651-ReWrapped/login_signup_tests
Browse files Browse the repository at this point in the history
Login signup tests
  • Loading branch information
preronaghosh authored Apr 2, 2024
2 parents 30a04a0 + 3ae618e commit 7aecc7a
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 97 deletions.
49 changes: 22 additions & 27 deletions src/containers/Signup.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { useNavigate } from "react-router-dom";
import axios from "axios";
import { Box, Button, TextField, Grid, Typography, Avatar, Link, FormControlLabel, Checkbox } from "@mui/material";
import {
Box,
Button,
TextField,
Grid,
Typography,
Avatar,
Link,
FormControlLabel,
Checkbox,
} from "@mui/material";
import { useFormik } from "formik";
import { validationSchema } from "../utility/passwordValidator";
// import { useAxios } from "../hooks/useAxios";
// import { passwordValidation } from "../utility/passwordValidator";
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
import { useDispatch } from "react-redux";
import { userDetailsActions } from "../slices/user/user-details-slice";

Expand All @@ -30,7 +40,6 @@ const Signup = () => {
withCredentials: true,
}
);
console.log(res);

if (res.status === 200) {
// store current user's email as global state
Expand Down Expand Up @@ -71,7 +80,7 @@ const Signup = () => {
alignItems="center"
>
<Grid item>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<Avatar sx={{ m: 1, bgcolor: "secondary.main" }}>
<LockOutlinedIcon />
</Avatar>
</Grid>
Expand Down Expand Up @@ -133,7 +142,7 @@ const Signup = () => {
<FormControlLabel
control={<Checkbox value="allowExtraEmails" color="primary" />}
label="I want to receive inspiration, marketing promotions and updates via email."
sx={{ color: 'grey' }}
sx={{ color: "grey" }}
/>
</Grid>
</Grid>
Expand All @@ -145,20 +154,20 @@ const Signup = () => {
style={{
marginTop: 20,
borderRadius: 25,
padding: '10px 20px',
fontWeight: 'bold',
boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.1)',
backgroundColor: 'black',
color: 'white',
width: '100%',
padding: "10px 20px",
fontWeight: "bold",
boxShadow: "0px 4px 8px rgba(0, 0, 0, 0.1)",
backgroundColor: "black",
color: "white",
width: "100%",
}}
>
Sign Up
</Button>
<Grid container justifyContent="flex-end" sx={{mt:2}}>
<Grid container justifyContent="flex-end" sx={{ mt: 2 }}>
<Grid item>
<Link href="/" variant="body2">
Already an user?
Already an user?
</Link>
</Grid>
</Grid>
Expand All @@ -168,17 +177,3 @@ const Signup = () => {
};

export default Signup;

// const { response, error, loading, refetch } = useAxios({
// axiosInstance: axios,
// method: "POST",
// url: "/register",
// requestData: {
// userData,
// },
// requestConfig: {
// headers: {
// //Custom headers, can't remember if I need this
// },
// },
// });
53 changes: 0 additions & 53 deletions src/hooks/useAxios.js

This file was deleted.

91 changes: 91 additions & 0 deletions src/tests/Login.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import Login from "../containers/Login";
import axios from "axios";

// Mock axios
jest.mock("axios");
const mockedUseNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUseNavigate,
}));

describe("Login Component Tests", () => {
beforeEach(() => {
jest.clearAllMocks();
});

test("Form can be filled and submit button is correctly pressed", async () => {
// Setup mock for axios.post
axios.post.mockResolvedValue({ status: 200 });

render(
<BrowserRouter>
<Login />
</BrowserRouter>
);

const emailInput = screen.getByLabelText(/email/i);
const passwordInput = screen.getByLabelText(/password/i);
const submitButton = screen.getByRole("button", { name: /login/i });

fireEvent.change(emailInput, { target: { value: "[email protected]" } });
fireEvent.change(passwordInput, { target: { value: "password123" } });

fireEvent.click(submitButton);

//wait for the axios post to have been called to ensure submission
await waitFor(() => expect(axios.post).toHaveBeenCalled());
});

test("navigates to '/' on unsuccessful login", async () => {
// Mock axios to simulate a failed login attempt
axios.post.mockResolvedValue({ status: 401 });

render(
<BrowserRouter>
<Login />
</BrowserRouter>
);

// Fill in the form and submit
fireEvent.change(screen.getByLabelText(/email/i), {
target: { value: "[email protected]" },
});
fireEvent.change(screen.getByLabelText(/password/i), {
target: { value: "wrongpassword" },
});
fireEvent.click(screen.getByRole("button", { name: /login/i }));

// Wait for the form submission to be handled
await waitFor(() => expect(axios.post).toHaveBeenCalled());

// Check if navigation was called with the expected argument
expect(mockedUseNavigate).toHaveBeenCalledWith("/");
});

test("catches error and navigates to '/' on login failure", async () => {
// Mock axios to simulate an error being thrown
axios.post.mockRejectedValue(new Error("Login failed"));

render(
<BrowserRouter>
<Login />
</BrowserRouter>
);

fireEvent.change(screen.getByLabelText(/email/i), {
target: { value: "[email protected]" },
});
fireEvent.change(screen.getByLabelText(/password/i), {
target: { value: "password" },
});
fireEvent.click(screen.getByRole("button", { name: /login/i }));

await waitFor(() => expect(axios.post).toHaveBeenCalled());

expect(mockedUseNavigate).toHaveBeenCalledWith("/");
});
});
141 changes: 141 additions & 0 deletions src/tests/Signup.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import Signup from "../containers/Signup";
import axios from "axios";
import { act } from "react-dom/test-utils";

//Mock functions
jest.mock("axios");
const mockedUseNavigate = jest.fn();
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useNavigate: () => mockedUseNavigate,
}));
jest.mock("react-redux", () => ({
useDispatch: () => jest.fn(),
}));

describe("Signup Component Tests", () => {
beforeEach(() => {
jest.clearAllMocks();
axios.post.mockClear();
});

test("form can be filled and submit button is correctly pressed", async () => {
axios.post.mockResolvedValue({ status: 200 }); // Simulate a successful signup

render(
<BrowserRouter>
<Signup />
</BrowserRouter>
);

// Target inputs by their label text
const emailInput = screen.getByLabelText("Email");
const nameInput = screen.getByLabelText("Username");
const passwordInput = screen.getByLabelText("Password");
const confirmPasswordInput = screen.getByLabelText("Confirm Password");

// Fill out the form
fireEvent.change(emailInput, { target: { value: "[email protected]" } });
fireEvent.change(nameInput, { target: { value: "newuser" } });
fireEvent.change(passwordInput, { target: { value: "Password123" } });
fireEvent.change(confirmPasswordInput, {
target: { value: "Password123" },
});

const submitButton = screen.getByRole("button", { name: /Sign up/i });
fireEvent.click(submitButton);

await waitFor(() => expect(axios.post).toHaveBeenCalled());

// Verify navigation to "/dashboard"
expect(mockedUseNavigate).toHaveBeenCalledWith("/dashboard");
});

test("does not submit the form when required fields are not filled", async () => {
render(
<BrowserRouter>
<Signup />
</BrowserRouter>
);

// Simulate user interactions with act
await act(async () => {
fireEvent.change(screen.getByLabelText("Email"), {
target: { value: "[email protected]" },
});

const submitButton = screen.getByRole("button", { name: /Sign up/i });
fireEvent.click(submitButton);
});

await waitFor(() => {
// Check that axios.post was not called since the form submission should be blocked by validation
expect(axios.post).not.toHaveBeenCalled();
});
});

test("handles non-200 status code gracefully", async () => {
axios.post.mockResolvedValue({ status: 400 });

render(
<BrowserRouter>
<Signup />
</BrowserRouter>
);

await act(async () => {
fireEvent.change(screen.getByLabelText("Email"), {
target: { value: "[email protected]" },
});
fireEvent.change(screen.getByLabelText("Username"), {
target: { value: "user" },
});
fireEvent.change(screen.getByLabelText("Password"), {
target: { value: "Password123" },
});
fireEvent.change(screen.getByLabelText("Confirm Password"), {
target: { value: "Password123" },
});
fireEvent.click(screen.getByRole("button", { name: /sign up/i }));
});

await waitFor(() => {
// Here, verify that the component does NOT navigate to the success page
expect(mockedUseNavigate).not.toHaveBeenCalledWith("/dashboard");
});
});

test("handles error during API call gracefully", async () => {
axios.post.mockRejectedValue(new Error("Network error"));

render(
<BrowserRouter>
<Signup />
</BrowserRouter>
);

// Simulate form submission
await act(async () => {
fireEvent.change(screen.getByLabelText("Email"), {
target: { value: "[email protected]" },
});
fireEvent.change(screen.getByLabelText("Username"), {
target: { value: "user" },
});
fireEvent.change(screen.getByLabelText("Password"), {
target: { value: "Password123" },
});
fireEvent.change(screen.getByLabelText("Confirm Password"), {
target: { value: "Password123" },
});
fireEvent.click(screen.getByRole("button", { name: /sign up/i }));
});

await waitFor(() => {
expect(mockedUseNavigate).not.toHaveBeenCalledWith("/dashboard");
});
});
});
Loading

0 comments on commit 7aecc7a

Please sign in to comment.