Skip to content

Commit 3d5d33a

Browse files
committed
Bugs - unit/integration tests added
1 parent 1bd515e commit 3d5d33a

19 files changed

+731
-2
lines changed

client/src/components/movie-details/Form.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const Form = (props: FormProps) => {
5050
Movie
5151
</h1>
5252
<form
53+
data-testid="form"
5354
className="space-y-4 md:space-y-6"
5455
onSubmit={handleSubmit(onSubmit)}
5556
>

client/src/components/movie-list/Card.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export const Card = ({
110110
</div>
111111
<div className="mt-auto w-full ">
112112
<Button
113+
data-testid="watch-now-button"
113114
onClick={() =>
114115
navigate(`/movie/${titleToSlug(movie.title)}`)
115116
}
@@ -133,6 +134,7 @@ export const Card = ({
133134

134135
{showAddModal && (
135136
<AddUpdateMovieModal
137+
data-testid="add-modal"
136138
movie={{
137139
id: "",
138140
userId: userId,

client/src/components/movie-reviews/Card.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export const Card = ({
108108
{canModify(userId, review.userId) && (
109109
<div className="flex justify-end space-x-5">
110110
<Button
111+
data-testid="edit-button"
111112
onClick={() => {
112113
setCurrentReview(review);
113114
setShowUpdateModal(true);
@@ -120,6 +121,7 @@ export const Card = ({
120121
<HiOutlinePencilSquare />
121122
</Button>
122123
<Button
124+
data-testid="delete-button"
123125
onClick={() => {
124126
setCurrentReview(review);
125127
setShowDeleteModal(true);

client/src/components/movie-reviews/Form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const Form = (props: FormProps) => {
118118
: "border-gray-300"
119119
} focus:ring-primary-600 focus:border-primary-600 block w-full rounded-lg border bg-gray-50 p-2.5 text-gray-900 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-blue-500 dark:focus:ring-blue-500 sm:text-sm`}
120120
>
121-
<option selected value={"5"}>
121+
<option defaultValue={"5"} value={"5"}>
122122
5
123123
</option>
124124
<option value={"4"}>4</option>

client/src/components/spinner/Spinner.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Spinner as Loader } from "flowbite-react";
22
export const Spinner = () => {
33
return (
4-
<div className="flex h-screen items-center justify-center bg-gray-50 dark:bg-gray-900">
4+
<div data-testid = "spinner" className="flex h-screen items-center justify-center bg-gray-50 dark:bg-gray-900">
55
<Loader size={"xl"} />
66
</div>
77
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { BrowserRouter } from "react-router-dom";
3+
import { AddUpdateMovieModal } from "../../components/movie-details/AddUpdateMovieModal";
4+
5+
describe("AddUpdateMovieModal component", () => {
6+
const mockMovie = {
7+
// mock movie object
8+
};
9+
10+
const mockOperation = "Create";
11+
const handleShowAddUpdateModal = vi.fn();
12+
const handleAddUpdateMovie = vi.fn();
13+
14+
it("calls createMutation.mutate with the correct arguments and navigates to the home page on success", () => {
15+
const mockCreateMutation = {
16+
mutate: vi.fn(),
17+
};
18+
19+
const mockNavigate = vi.fn();
20+
21+
22+
render(
23+
<BrowserRouter >
24+
<AddUpdateMovieModal
25+
createMutation={mockCreateMutation}
26+
navigate={mockNavigate}
27+
/>
28+
</BrowserRouter>
29+
);
30+
31+
// Call the handleAddUpdateMovie function with the mock movie and operation
32+
handleAddUpdateMovie(mockMovie, mockOperation);
33+
34+
// Assert that createMutation.mutate was called with the correct arguments
35+
expect(mockCreateMutation.mutate).toHaveBeenCalledWith(mockMovie, {
36+
onSuccess: expect.any(Function),
37+
onError: expect.any(Function),
38+
});
39+
40+
// Simulate a successful mutation
41+
mockCreateMutation.mutate.mock.calls[0][1].onSuccess();
42+
43+
// Assert that the success alert was displayed
44+
expect(screen.getByText("Movie added successfully")).toBeInTheDocument();
45+
46+
// Assert that handleShowAddUpdateModal was called
47+
expect(handleShowAddUpdateModal).toHaveBeenCalled();
48+
49+
// Assert that navigate was called with the correct path
50+
expect(mockNavigate).toHaveBeenCalledWith("/");
51+
52+
// Reset mock functions
53+
mockCreateMutation.mutate.mockReset();
54+
mockNavigate.mockReset();
55+
});
56+
57+
it("calls updateMutation.mutate with the correct arguments and navigates to the home page on success", () => {
58+
const mockUpdateMutation = {
59+
mutate: vi.fn(),
60+
};
61+
62+
const mockNavigate = vi.fn();
63+
64+
render(
65+
<BrowserRouter>
66+
<AddUpdateMovieModal
67+
updateMutation={mockUpdateMutation}
68+
navigate={mockNavigate}
69+
/>
70+
</BrowserRouter>
71+
);
72+
73+
// Call the handleAddUpdateMovie function with the mock movie and operation
74+
handleAddUpdateMovie(mockMovie, "Update");
75+
76+
// Assert that updateMutation.mutate was called with the correct arguments
77+
expect(mockUpdateMutation.mutate).toHaveBeenCalledWith(mockMovie, {
78+
onSuccess: expect.any(Function),
79+
onError: expect.any(Function),
80+
});
81+
82+
// Simulate a successful mutation
83+
mockUpdateMutation.mutate.mock.calls[0][1].onSuccess();
84+
85+
// Assert that the success alert was displayed
86+
expect(screen.getByText("Movie updated successfully")).toBeInTheDocument();
87+
88+
// Assert that handleShowAddUpdateModal was called
89+
expect(handleShowAddUpdateModal).toHaveBeenCalled();
90+
91+
// Assert that navigate was called with the correct path
92+
expect(mockNavigate).toHaveBeenCalledWith("/");
93+
94+
// Reset mock functions
95+
mockUpdateMutation.mutate.mockReset();
96+
mockNavigate.mockReset();
97+
});
98+
99+
it("logs an error message for an invalid operation", () => {
100+
console.log = vi.fn();
101+
102+
// render(
103+
// <BrowserRouter>
104+
// <AddUpdateMovieModal />
105+
// </BrowserRouter>
106+
// );
107+
108+
// Call the handleAddUpdateMovie function with the mock movie and an invalid operation
109+
handleAddUpdateMovie(mockMovie, "InvalidOperation");
110+
111+
// Assert that console.log was called with the error message
112+
expect(console.log).toHaveBeenCalledWith("Invalid operation");
113+
114+
});
115+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { render, screen, fireEvent } from "@testing-library/react";
2+
import { AddUpdateReviewModal } from "../../components/movie-reviews/AddUpdateReviewModal";
3+
4+
describe('AddUpdateReviewModal component', () => {
5+
const mockReview = {
6+
id: "1",
7+
title: "Test Review",
8+
description: "This is a test review",
9+
rating: "5",
10+
movieId: "123",
11+
userId: "456",
12+
};
13+
const mockOperation = "Create";
14+
const mockShow = true;
15+
const mockHandleShowAddUpdateModal = vi.fn();
16+
const mockHandleAddUpdateReview = vi.fn();
17+
18+
beforeEach(() => {
19+
const mockHandleShowAddUpdateModal = vi.fn();
20+
21+
render(
22+
<AddUpdateReviewModal
23+
review={mockReview}
24+
operation={mockOperation}
25+
show={mockShow}
26+
handleShowAddUpdateModal={mockHandleShowAddUpdateModal}
27+
/>
28+
);
29+
});
30+
31+
it('renders the modal with correct props', () => {
32+
const modal = screen.getByRole('dialog');
33+
expect(modal).toBeInTheDocument();
34+
expect(modal).toHaveClass('backdrop-blur-sm');
35+
expect(modal).toHaveAttribute('size', 'md');
36+
});
37+
38+
it('renders the form inside the modal', () => {
39+
const form = screen.getByLabelText('Title');
40+
expect(form).toBeInTheDocument();
41+
});
42+
43+
it('calls handleShowAddUpdateModal when modal is closed', () => {
44+
const modal = screen.getByRole('dialog');
45+
fireEvent.click(modal);
46+
expect(mockHandleShowAddUpdateModal).toHaveBeenCalled();
47+
});
48+
49+
it('calls handleAddUpdateReview with correct data on form submission', () => {
50+
51+
const submitButton = screen.getByRole('button', { name: mockOperation });
52+
fireEvent.click(submitButton);
53+
expect(mockHandleAddUpdateReview).toHaveBeenCalledWith(
54+
mockReview,
55+
mockOperation
56+
);
57+
});
58+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { render, screen, fireEvent } from "@testing-library/react";
2+
import { DeleteConfirmationModal } from "../../components/modal/DeleteConfirmationModal";
3+
4+
describe("DeleteConfirmationModal component", () => {
5+
const mockProps = {
6+
type: "review",
7+
show: true,
8+
handleShowDeleteModal: vitest.fn(),
9+
reviewId: "123",
10+
movieId: "456",
11+
message: "Are you sure you want to delete?",
12+
handleDeletion: vitest.fn(),
13+
};
14+
15+
beforeEach(() => {
16+
mockProps.handleShowDeleteModal.mockClear();
17+
render(<DeleteConfirmationModal
18+
type="review"
19+
show={true}
20+
handleShowDeleteModal={mockProps.handleShowDeleteModal}
21+
reviewId="123"
22+
movieId="456"
23+
message="Are you sure you want to delete?"
24+
handleDeletion={mockProps.handleDeletion}
25+
/>);
26+
});
27+
28+
it("renders the modal with the correct message", () => {
29+
const messageElement = screen.getByText(mockProps.message);
30+
expect(messageElement).toBeInTheDocument();
31+
});
32+
33+
it("calls handleDeletion and handleShowDeleteModal when 'Yes, I'm sure' button is clicked", () => {
34+
const yesButton = screen.getByText("Yes, I'm sure");
35+
fireEvent.click(yesButton);
36+
expect(mockProps.handleDeletion).toHaveBeenCalledTimes(1);
37+
expect(mockProps.handleShowDeleteModal).toHaveBeenCalledTimes(1);
38+
});
39+
40+
it("calls handleShowDeleteModal when 'No, cancel' button is clicked", () => {
41+
const cancelButton = screen.getByText("No, cancel");
42+
fireEvent.click(cancelButton);
43+
expect(mockProps.handleShowDeleteModal).toHaveBeenCalledTimes(1);
44+
});
45+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { render, screen, fireEvent } from "@testing-library/react";
2+
import { Card } from "../../components/movie-details/Card";
3+
4+
describe("Card component", () => {
5+
const mockMovie = {
6+
id: "1",
7+
title: "Test Movie",
8+
description: "Test Description",
9+
userId: "user1",
10+
};
11+
12+
const mockUserId = "user1";
13+
14+
it("renders movie details correctly", () => {
15+
render(<Card movie={mockMovie} userId={mockUserId} />);
16+
17+
expect(screen.getByText(mockMovie.title)).toBeInTheDocument();
18+
expect(screen.getByText(mockMovie.description)).toBeInTheDocument();
19+
});
20+
21+
it("shows delete confirmation modal when delete button is clicked", () => {
22+
render(<Card movie={mockMovie} userId={mockUserId} />);
23+
24+
const deleteButton = screen.getByTestId("delete-button");
25+
fireEvent.click(deleteButton);
26+
27+
expect(screen.getByText("Are you sure you want to delete this movie?")).toBeInTheDocument();
28+
});
29+
30+
it("shows update modal when update button is clicked", () => {
31+
render(<Card movie={mockMovie} userId={mockUserId} />);
32+
33+
const updateButton = screen.getByTestId("update-button");
34+
fireEvent.click(updateButton);
35+
36+
expect(screen.getByText("Update Movie")).toBeInTheDocument();
37+
});
38+
39+
it("calls deleteMutation.mutate and navigates to home page when movie is deleted", () => {
40+
const mockDeleteMutation = {
41+
mutate: vi.fn(),
42+
};
43+
44+
const mockNavigate = vi.fn();
45+
46+
render(
47+
<Card
48+
movie={mockMovie}
49+
userId={mockUserId}
50+
deleteMutation={mockDeleteMutation}
51+
navigate={mockNavigate}
52+
/>
53+
);
54+
55+
const deleteButton = screen.getByTestId("delete-button");
56+
fireEvent.click(deleteButton);
57+
58+
const confirmButton = screen.getByText("Confirm");
59+
fireEvent.click(confirmButton);
60+
61+
expect(mockDeleteMutation.mutate).toHaveBeenCalledWith(mockMovie.id, {
62+
onSuccess: expect.any(Function),
63+
onError: expect.any(Function),
64+
});
65+
66+
// Simulate a successful deletion
67+
mockDeleteMutation.mutate.mock.calls[0][1].onSuccess();
68+
69+
expect(screen.getByText("Movie Deleted")).toBeInTheDocument();
70+
expect(mockNavigate).toHaveBeenCalledWith("/");
71+
});
72+
});

0 commit comments

Comments
 (0)