diff --git a/packages/web/src/components/chat/FriendsPage.test.tsx b/packages/web/src/components/chat/FriendsPage.test.tsx index d6aead21..9a7c1e9a 100644 --- a/packages/web/src/components/chat/FriendsPage.test.tsx +++ b/packages/web/src/components/chat/FriendsPage.test.tsx @@ -7,6 +7,21 @@ import { useSocialStore, type TaggedFriend, type TaggedFriendRequest } from '../ import { useSpaceStore } from '../../stores/spaceStore'; import type { Friend, FriendRequest } from '@backspace/shared'; +// Mock the mascot animation hook +vi.mock('../../hooks/useMascotAnimation', () => ({ + useMascotAnimation: vi.fn(), +})); + +// Stub AudioManager to avoid AudioWorkletNode reference error in jsdom +vi.mock('../../audio/AudioManager', () => ({ + AudioManager: { + getInstance: vi.fn().mockReturnValue({ + setOutputDevice: vi.fn(), + setVolume: vi.fn(), + }), + }, +})); + // Mock the api module vi.mock('../../api/client', () => ({ api: { @@ -365,4 +380,36 @@ describe('FriendsPage', () => { }); }); }); + + describe('Empty state mascot messages', () => { + it('shows "No one\'s online right now." in online tab when no friends online', () => { + useSocialStore.setState({ friends: [], requests: [] }); + renderFriendsPage(); + + expect(screen.getByText("No one's online right now.")).toBeInTheDocument(); + expect(screen.queryByText(/Wumpus/)).not.toBeInTheDocument(); + }); + + it('shows "No friends yet — add someone!" in all tab when no friends', async () => { + const user = userEvent.setup(); + useSocialStore.setState({ friends: [], requests: [] }); + renderFriendsPage(); + + await user.click(screen.getByText('All')); + + expect(screen.getByText('No friends yet — add someone!')).toBeInTheDocument(); + expect(screen.queryByText(/Wumpus/)).not.toBeInTheDocument(); + }); + + it('shows "No pending requests — Nori is napping." in pending tab when empty', async () => { + const user = userEvent.setup(); + useSocialStore.setState({ friends: [], requests: [] }); + renderFriendsPage(); + + await user.click(screen.getByText('Pending')); + + expect(screen.getByText('No pending requests — Nori is napping.')).toBeInTheDocument(); + expect(screen.queryByText(/Wumpus/)).not.toBeInTheDocument(); + }); + }); }); diff --git a/packages/web/src/components/chat/FriendsPage.tsx b/packages/web/src/components/chat/FriendsPage.tsx index 735859d8..5ce7a8a8 100644 --- a/packages/web/src/components/chat/FriendsPage.tsx +++ b/packages/web/src/components/chat/FriendsPage.tsx @@ -10,6 +10,7 @@ import { MemberListToggleButton } from '../layout/MemberListToggleButton'; import { LoadingSpinner } from '../ui/LoadingSpinner'; import { getAvatarGradient } from '../../utils/gradients'; import { api } from '../../api/client'; +import { Mascot } from '../ui/Mascot'; type Tab = 'online' | 'all' | 'pending' | 'add'; @@ -97,9 +98,9 @@ export function FriendsPage({ mobile }: FriendsPageProps) { Online — {onlineFriends.length} {onlineFriends.length === 0 ? ( -
- (e.target as any).style.display='none'} /> -

No one's around to play with Wumpus.

+
+ +

No one's online right now.

) : ( onlineFriends.map(friend => ( @@ -115,8 +116,9 @@ export function FriendsPage({ mobile }: FriendsPageProps) { All Friends — {friends.length} {friends.length === 0 ? ( -
-

Wumpus is waiting on friends. You can add them!

+
+ +

No friends yet — add someone!

) : ( friends.map(friend => ( @@ -132,8 +134,9 @@ export function FriendsPage({ mobile }: FriendsPageProps) { Pending — {pendingIncoming.length + pendingOutgoing.length} {[...pendingIncoming, ...pendingOutgoing].length === 0 ? ( -
-

There are no pending friend requests. Here's Wumpus for now!

+
+ +

No pending requests — Nori is napping.

) : ( <>