diff --git a/frontend/src/__tests__/components/Navbar.test.tsx b/frontend/src/__tests__/components/Navbar.test.tsx
index 05f6bf3..d009fe1 100644
--- a/frontend/src/__tests__/components/Navbar.test.tsx
+++ b/frontend/src/__tests__/components/Navbar.test.tsx
@@ -86,12 +86,6 @@ describe('Navbar', () => {
expect(screen.getByPlaceholderText('Search items...')).toBeInTheDocument();
});
- it('should render location input', () => {
- renderWithRouter();
-
- expect(screen.getByPlaceholderText('City or ZIP')).toBeInTheDocument();
- });
-
it('should render search button', () => {
renderWithRouter();
@@ -122,36 +116,6 @@ describe('Navbar', () => {
expect(mockNavigate).toHaveBeenCalledWith('/items?search=tent');
});
- it('should append city to search URL', () => {
- renderWithRouter();
-
- const searchInput = screen.getByPlaceholderText('Search items...');
- const locationInput = screen.getByPlaceholderText('City or ZIP');
-
- fireEvent.change(searchInput, { target: { value: 'kayak' } });
- fireEvent.change(locationInput, { target: { value: 'Seattle' } });
-
- const searchButton = document.querySelector('button.btn-outline-secondary') as HTMLButtonElement;
- fireEvent.click(searchButton);
-
- expect(mockNavigate).toHaveBeenCalledWith('/items?search=kayak&city=Seattle');
- });
-
- it('should append zipCode when location is a zip code', () => {
- renderWithRouter();
-
- const searchInput = screen.getByPlaceholderText('Search items...');
- const locationInput = screen.getByPlaceholderText('City or ZIP');
-
- fireEvent.change(searchInput, { target: { value: 'bike' } });
- fireEvent.change(locationInput, { target: { value: '98101' } });
-
- const searchButton = document.querySelector('button.btn-outline-secondary') as HTMLButtonElement;
- fireEvent.click(searchButton);
-
- expect(mockNavigate).toHaveBeenCalledWith('/items?search=bike&zipCode=98101');
- });
-
it('should clear search fields after search', () => {
renderWithRouter();
@@ -169,16 +133,38 @@ describe('Navbar', () => {
it('should show login button when user is not logged in', () => {
renderWithRouter();
- expect(screen.getByRole('button', { name: 'Login or Sign Up' })).toBeInTheDocument();
+ // There are two login buttons (mobile + desktop)
+ const loginButtons = screen.getAllByRole('button', { name: 'Login or Sign Up' });
+ expect(loginButtons.length).toBeGreaterThan(0);
});
it('should call openAuthModal when login button is clicked', () => {
renderWithRouter();
- fireEvent.click(screen.getByRole('button', { name: 'Login or Sign Up' }));
+ // Click the first login button (either mobile or desktop)
+ const loginButtons = screen.getAllByRole('button', { name: 'Login or Sign Up' });
+ fireEvent.click(loginButtons[0]);
expect(mockOpenAuthModal).toHaveBeenCalledWith('login');
});
+
+ it('should show Forum link when logged out', () => {
+ renderWithRouter();
+
+ // There are two Forum links (mobile + desktop), both should link to /forum
+ const forumLinks = screen.getAllByRole('link', { name: /Forum/i });
+ expect(forumLinks.length).toBeGreaterThan(0);
+ forumLinks.forEach(link => {
+ expect(link).toHaveAttribute('href', '/forum');
+ });
+ });
+
+ it('should show hamburger icon for mobile toggle when logged out', () => {
+ renderWithRouter();
+
+ const hamburgerIcon = document.querySelector('.bi-list');
+ expect(hamburgerIcon).toBeInTheDocument();
+ });
});
describe('Logged In State', () => {
@@ -191,10 +177,11 @@ describe('Navbar', () => {
};
});
- it('should show user name when logged in', () => {
+ it('should show user avatar when logged in', () => {
renderWithRouter();
- expect(screen.getByText('John')).toBeInTheDocument();
+ // Avatar displays user initials (JD for John Doe) - may appear multiple times (mobile + desktop)
+ expect(screen.getAllByText('JD').length).toBeGreaterThan(0);
});
it('should not show login button when logged in', () => {
@@ -250,19 +237,26 @@ describe('Navbar', () => {
});
});
- describe('Start Earning Link', () => {
- it('should show Start Earning link', () => {
- renderWithRouter();
-
- expect(screen.getByRole('link', { name: 'Start Earning' })).toHaveAttribute('href', '/create-item');
- });
- });
-
describe('Mobile Navigation', () => {
it('should render mobile toggle button', () => {
renderWithRouter();
expect(screen.getByLabelText('Toggle navigation')).toBeInTheDocument();
});
+
+ it('should show avatar in mobile toggle when logged in', () => {
+ mockUser = {
+ id: 'user-123',
+ firstName: 'John',
+ lastName: 'Doe',
+ email: 'john@example.com',
+ };
+
+ renderWithRouter();
+
+ // Should have avatar with initials, not hamburger icon
+ expect(screen.getAllByText('JD').length).toBeGreaterThan(0);
+ expect(document.querySelector('.bi-list')).not.toBeInTheDocument();
+ });
});
});
diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx
index 0ff721a..626bd06 100644
--- a/frontend/src/components/Navbar.tsx
+++ b/frontend/src/components/Navbar.tsx
@@ -3,6 +3,7 @@ import { Link, useNavigate } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
import { useSocket } from "../contexts/SocketContext";
import { rentalAPI, messageAPI } from "../services/api";
+import Avatar from "./Avatar";
const Navbar: React.FC = () => {
const { user, logout, openAuthModal } = useAuth();
@@ -137,7 +138,7 @@ const Navbar: React.FC = () => {
- {/* Mobile avatar toggle */}
+ {/* Mobile menu toggle */}
-
-
+
+
{user ? (
<>
-
@@ -210,29 +215,26 @@ const Navbar: React.FC = () => {
{pendingRequestsCount + unreadMessagesCount}
)}
-
- {user.firstName}
+
>
) : (
- -
-
-
+ <>
+ -
+
+ Forum
+
+
+ Forum
+
+
+ -
+
+
+
+ >
)}