From a4e578d7772442d7284b40104527dd8a000e2804 Mon Sep 17 00:00:00 2001 From: Heisjabo Date: Tue, 30 Jul 2024 14:03:04 +0200 Subject: [PATCH] fix(chat): users should be able to receive messages in real time --- src/App.tsx | 6 +-- src/__test__/addProducts.test.tsx | 5 ++ src/__test__/productcard.test.tsx | 33 +++++++++++++ src/__test__/userList.test.tsx | 9 ++++ src/components/dashboard/Header.tsx | 4 +- src/components/dashboard/SideBar.tsx | 4 +- src/components/dashboard/Spinner.tsx | 2 +- .../dashboard/admin/AdminSideBar.tsx | 2 +- .../dashboard/products/ProductsTable.tsx | 5 +- src/page-sections/UserList.tsx | 16 ++++++- src/pages/ChatPage.tsx | 48 ++++++++++++------- 11 files changed, 103 insertions(+), 31 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 38ee2d3..4414b75 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -49,11 +49,11 @@ const App: React.FC = () => { {location.pathname !== "/chat" && location.pathname !== "/login" && location.pathname !== "/register" && ( - -
+
(window.location.href = "/chat")}> +
- +
)} ); diff --git a/src/__test__/addProducts.test.tsx b/src/__test__/addProducts.test.tsx index 6624942..34f0d2e 100644 --- a/src/__test__/addProducts.test.tsx +++ b/src/__test__/addProducts.test.tsx @@ -55,6 +55,11 @@ describe("FileUpload component", () => { new File(["dummy content"], "example.png", { type: "image/png" }), ]; + jest.mock("react-router-dom", () => ({ + ...jest.requireActual("react-router-dom"), + useParams: jest.fn(), + })); + beforeEach(() => { (useDropzone as jest.Mock).mockImplementation(() => ({ getRootProps: jest.fn(() => ({ onClick: () => {} })), diff --git a/src/__test__/productcard.test.tsx b/src/__test__/productcard.test.tsx index 6176f53..33ecb36 100644 --- a/src/__test__/productcard.test.tsx +++ b/src/__test__/productcard.test.tsx @@ -77,6 +77,39 @@ describe("ProductCard Component", () => { // expect(addToCartButton).toBeDefined(); }); + test("renders rating and review count correctly", () => { + render( + + + + + , + ); + + const rating = screen.getByTestId("rating"); + const reviewCount = screen.getByTestId("review"); + + expect(rating).toBeDefined(); + expect(reviewCount).toBeDefined(); + }); + + test("truncates long product names", () => { + const longNameProduct = { + ...product, + name: "This is a very long product name that should be truncated", + }; + render( + + + + + , + ); + + const productName = screen.getByTestId("product-name"); + expect(productName.textContent).toHaveLength(15); + }); + test("renders wishlist and view details buttons", () => { render( diff --git a/src/__test__/userList.test.tsx b/src/__test__/userList.test.tsx index 8cbaeb8..d26facb 100644 --- a/src/__test__/userList.test.tsx +++ b/src/__test__/userList.test.tsx @@ -6,8 +6,17 @@ import MockAdapter from "axios-mock-adapter"; import UserList from "../page-sections/UserList"; import chatSlice from "../redux/reducers/chatSlice"; import api from "../redux/api/api"; +import { socket } from "../config/socket"; const mockApi = new MockAdapter(api); + +jest.mock("../config/socket", () => ({ + socket: { + on: jest.fn(), + off: jest.fn(), + }, +})); + const mockStore = (initialState) => configureStore({ reducer: { diff --git a/src/components/dashboard/Header.tsx b/src/components/dashboard/Header.tsx index 1ee19b6..75fcc71 100644 --- a/src/components/dashboard/Header.tsx +++ b/src/components/dashboard/Header.tsx @@ -54,7 +54,7 @@ const Header: React.FC = ({ toggleSidebar }) => { return ( <> -
+
@@ -67,7 +67,7 @@ const Header: React.FC = ({ toggleSidebar }) => {
diff --git a/src/components/dashboard/SideBar.tsx b/src/components/dashboard/SideBar.tsx index 7110c52..df04242 100644 --- a/src/components/dashboard/SideBar.tsx +++ b/src/components/dashboard/SideBar.tsx @@ -26,8 +26,8 @@ const SideBar: React.FC = ({ isOpen }) => { isOpen ? "translate-x-0" : "-translate-x-full" } lg:translate-x-0`} > -
-
+
+
eagles diff --git a/src/components/dashboard/Spinner.tsx b/src/components/dashboard/Spinner.tsx index 940ec9e..2294736 100644 --- a/src/components/dashboard/Spinner.tsx +++ b/src/components/dashboard/Spinner.tsx @@ -1,5 +1,5 @@ const Spinner = () => ( - + = ({ isOpen }) => { isOpen ? "translate-x-0" : "-translate-x-full" } lg:translate-x-0`} > -
+
eagles diff --git a/src/components/dashboard/products/ProductsTable.tsx b/src/components/dashboard/products/ProductsTable.tsx index c5e8492..3941abe 100644 --- a/src/components/dashboard/products/ProductsTable.tsx +++ b/src/components/dashboard/products/ProductsTable.tsx @@ -162,10 +162,7 @@ const ProductsTable: React.FC = () => { ) : products.length === 0 ? ( - + No products found. diff --git a/src/page-sections/UserList.tsx b/src/page-sections/UserList.tsx index 5a4ce15..61314a5 100644 --- a/src/page-sections/UserList.tsx +++ b/src/page-sections/UserList.tsx @@ -8,6 +8,7 @@ import { HiMiniUserGroup } from "react-icons/hi2"; import { useAppDispatch } from "../redux/hooks"; import Spinner from "../components/dashboard/Spinner"; import { fetchChats, fetchUsers } from "../redux/reducers/chatSlice"; +import { socket } from "../config/socket"; interface UserListProps { onUserSelect: (chat: any | null, user: any) => void; @@ -38,6 +39,17 @@ const UserList: React.FC = ({ useEffect(() => { dispatch(fetchChats()); dispatch(fetchUsers()); + + const handlePrivateMessage = () => { + dispatch(fetchChats()); + dispatch(fetchUsers()); + }; + + socket.on("private message recieved", handlePrivateMessage); + + return () => { + socket.off("private message recieved", handlePrivateMessage); + }; }, [dispatch]); useEffect(() => { @@ -114,7 +126,7 @@ const UserList: React.FC = ({ @@ -193,7 +205,7 @@ const UserList: React.FC = ({ {chat.messages.length > 0 ? chat.messages[ chat.messages.length - 1 - ].message.substring(0, 20) + ].message.substring(0, 15) : "No messages yet"} ...

diff --git a/src/pages/ChatPage.tsx b/src/pages/ChatPage.tsx index 61d5545..1c94329 100644 --- a/src/pages/ChatPage.tsx +++ b/src/pages/ChatPage.tsx @@ -1,7 +1,6 @@ import React, { useState, useEffect, useRef } from "react"; import { useSelector } from "react-redux"; import { Link } from "react-router-dom"; -import { MdSportsGolf } from "react-icons/md"; import UserList from "../page-sections/UserList"; import ChatWindow from "../page-sections/ChatWindow"; @@ -31,8 +30,20 @@ const ChatPage: React.FC = () => { setRefetch(true); }; + const handlePastMessages = (pastMessages: any[]) => { + setPublicMessages( + pastMessages.map((msg) => ({ + isOwner: msg.sender === profile?.name, + message: msg.message, + sender: msg.sender, + createdAt: msg.createdAt, + })), + ); + }; + useEffect(() => { dispatch(fetchUser()); + socket.on("past messages", handlePastMessages); }, [dispatch]); useEffect(() => { @@ -43,32 +54,31 @@ const ChatPage: React.FC = () => { }, []); useEffect(() => { - const handleConnect = () => { - socket.emit("private chats"); - }; + socket.on("past messages", handlePastMessages); + }, [isPublicChat]); + useEffect(() => { const handleChatMessage = (msg: any) => { if (!publicMessageIds.current.has(msg.id)) { setPublicMessages((prevMessages) => [...prevMessages, msg]); publicMessageIds.current.add(msg.id); } }; + socket.on("chat message", handleChatMessage); + socket.on("past messages", handlePastMessages); - const handlePastMessages = (pastMessages: any[]) => { - setPublicMessages( - pastMessages.map((msg) => ({ - isOwner: msg.sender === profile?.name, - message: msg.message, - sender: msg.sender, - createdAt: msg.createdAt, - })), - ); + return () => { + socket.off("chat message", handleChatMessage); + socket.off("past messages", handlePastMessages); }; + }, [publicMessageIds, selectedChat]); + useEffect(() => { + const handleConnect = () => { + socket.emit("private chats"); + }; socket.on("connect", handleConnect); - socket.on("chat message", handleChatMessage); - socket.on("past messages", handlePastMessages); - }, [publicMessages]); + }, [selectedChat]); useEffect(() => { const handlePrivateMessage = (message: any) => { @@ -191,6 +201,12 @@ const ChatPage: React.FC = () => { })); try { + socket.emit("private chat message", { + sender: profile?.username, + userId: profile?.id, + receiverId: newChatUser.id, + message: text, + }); await dispatch( sendMessage({ message: text, id: newChatUser.id }), ).unwrap();