diff --git a/__tests__/Home.test.jsx b/__tests__/Home.test.jsx
new file mode 100644
index 0000000..bb0ea6f
--- /dev/null
+++ b/__tests__/Home.test.jsx
@@ -0,0 +1,60 @@
+import React from "react";
+import { render, screen } from "@testing-library/react";
+import { Provider } from "react-redux";
+import configureStore from "redux-mock-store";
+import Home from "src/pages/Home";
+import { useGetChatsQuery } from "../backend/redux/api_slice";
+
+// Mock Redux store
+const mockStore = configureStore([]);
+
+// Mock the useGetChatsQuery hook
+jest.mock("src/backend/redux/api_slice", () => ({
+ useGetChatsQuery: jest.fn(),
+}));
+
+describe("Home Page", () => {
+ let store;
+
+ beforeEach(() => {
+ store = mockStore({});
+ });
+
+ test("renders Home page with loading state", () => {
+ useGetChatsQuery.mockReturnValue({ isLoading: true });
+
+ render(
+
+
+
+ );
+
+ expect(screen.getByText(/loading/i)).toBeInTheDocument();
+ });
+
+ test("renders Home page with chat data", () => {
+ const chatsData = [{ id: 1, name: "Chat 1" }, { id: 2, name: "Chat 2" }];
+ useGetChatsQuery.mockReturnValue({ data: chatsData, isLoading: false });
+
+ render(
+
+
+
+ );
+
+ expect(screen.getByText("Chat 1")).toBeInTheDocument();
+ expect(screen.getByText("Chat 2")).toBeInTheDocument();
+ });
+
+ test("renders error message when fetching chats fails", () => {
+ useGetChatsQuery.mockReturnValue({ error: true, isLoading: false });
+
+ render(
+
+
+
+ );
+
+ expect(screen.getByText(/error/i)).toBeInTheDocument();
+ });
+});
diff --git a/__tests__/SignIn.test.jsx b/__tests__/SignIn.test.jsx
new file mode 100644
index 0000000..29204ba
--- /dev/null
+++ b/__tests__/SignIn.test.jsx
@@ -0,0 +1,52 @@
+import React from "react";
+import { render, screen, fireEvent } from "@testing-library/react";
+import SignIn from "../pages/SignIn";
+import { displayMessage } from "../backend/notifications/notifications";
+import { post } from "../backend/api";
+
+// Mock the displayMessage and post functions
+jest.mock("../backend/notifications/notifications", () => ({
+ displayMessage: jest.fn(),
+}));
+jest.mock("../backend/api", () => ({
+ post: jest.fn(),
+}));
+
+describe("SignIn Page", () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ test("renders SignIn form", () => {
+ render();
+ expect(screen.getByLabelText(/username/i)).toBeInTheDocument();
+ expect(screen.getByLabelText(/password/i)).toBeInTheDocument();
+ expect(screen.getByText(/sign in/i)).toBeInTheDocument();
+ });
+
+ test("displays error message on failed login", async () => {
+ post.mockResolvedValueOnce({ ok: false, data: { message: "Invalid credentials" } });
+
+ render();
+ fireEvent.change(screen.getByLabelText(/username/i), { target: { value: "user" } });
+ fireEvent.change(screen.getByLabelText(/password/i), { target: { value: "password" } });
+ fireEvent.click(screen.getByText(/sign in/i));
+
+ expect(await screen.findByText(/invalid credentials/i)).toBeInTheDocument();
+ expect(displayMessage).toHaveBeenCalledWith("Invalid credentials", "error");
+ });
+
+ test("displays additional info message after multiple login attempts", async () => {
+ post.mockResolvedValueOnce({ ok: false, data: { message: "Invalid credentials" } });
+
+ render();
+ fireEvent.change(screen.getByLabelText(/username/i), { target: { value: "user" } });
+ fireEvent.change(screen.getByLabelText(/password/i), { target: { value: "password" } });
+
+ // Simulate two failed login attempts
+ fireEvent.click(screen.getByText(/sign in/i));
+ fireEvent.click(screen.getByText(/sign in/i));
+
+ expect(displayMessage).toHaveBeenCalledWith("Note that you need to enter your ID name", "info");
+ });
+});
diff --git a/jest.config.ts b/jest.config.ts
index 2bb5326..f158775 100644
--- a/jest.config.ts
+++ b/jest.config.ts
@@ -17,6 +17,10 @@ const config: Config = {
// transform: {
// '^.+\\.(ts|tsx|js|jsx)$': 'babel-jest',
// },
+ moduleNameMapper: {
+ "^@/src/(.*)$": "/src/$1", // Map '@/src' to the 'src' folder
+ "^src/(.*)$": "/src/$1", // Map 'src' to the 'src' folder
+ },
moduleFileExtensions: [...defaults.moduleFileExtensions, 'ts', 'tsx', 'js', 'jsx'],
};
diff --git a/package-lock.json b/package-lock.json
index 3a7d8a7..5339fd8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -42,6 +42,7 @@
"babel-jest": "^29.7.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
+ "redux-mock-store": "^1.5.4",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2"
}
@@ -11778,6 +11779,16 @@
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT"
},
+ "node_modules/redux-mock-store": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.4.tgz",
+ "integrity": "sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lodash.isplainobject": "^4.0.6"
+ }
+ },
"node_modules/redux-thunk": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
diff --git a/package.json b/package.json
index 1a15561..d2ccec1 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
"babel-jest": "^29.7.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
+ "redux-mock-store": "^1.5.4",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2"
}
diff --git a/src.zip b/src.zip
new file mode 100644
index 0000000..5f00fec
Binary files /dev/null and b/src.zip differ