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 */}