veza/apps/web/src/features/auth/components/UserProfile.test.tsx

151 lines
3.8 KiB
TypeScript
Raw Normal View History

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { UserProfile } from './UserProfile';
import { apiClient } from '@/services/api/client';
// Mock apiClient
vi.mock('@/services/api/client', () => ({
apiClient: {
get: vi.fn(),
},
}));
// Mock ResizeObserver for tests
global.ResizeObserver = vi.fn().mockImplementation(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}));
const TestWrapper = ({ children }: { children: React.ReactNode }) => {
return <BrowserRouter>{children}</BrowserRouter>;
};
describe('UserProfile Component', () => {
beforeEach(() => {
vi.clearAllMocks();
});
// Test 1: Affiche le nombre de sessions actives
it('should display active sessions count', async () => {
vi.mocked(apiClient.get).mockResolvedValue({
data: {
sessions: [
2025-12-13 02:34:34 +00:00
{
id: '1',
ip_address: '192.168.1.1',
user_agent: 'Mozilla/5.0',
last_activity: '2024-01-15T10:30:00Z',
created_at: '2024-01-10T08:00:00Z',
is_current: true,
},
{
id: '2',
ip_address: '192.168.1.2',
user_agent: 'Mozilla/5.0',
last_activity: '2024-01-15T09:00:00Z',
created_at: '2024-01-12T12:00:00Z',
is_current: false,
},
],
count: 2,
},
});
render(
<TestWrapper>
<UserProfile />
2025-12-13 02:34:34 +00:00
</TestWrapper>,
);
await waitFor(() => {
expect(screen.getByText('Active Sessions')).toBeInTheDocument();
expect(screen.getByText('2')).toBeInTheDocument();
});
expect(apiClient.get).toHaveBeenCalledWith('/auth/sessions');
});
// Test 2: Affiche 0 quand il n'y a pas de sessions
it('should display 0 when there are no sessions', async () => {
vi.mocked(apiClient.get).mockResolvedValue({
data: {
sessions: [],
count: 0,
},
});
render(
<TestWrapper>
<UserProfile />
2025-12-13 02:34:34 +00:00
</TestWrapper>,
);
await waitFor(() => {
expect(screen.getByText('0')).toBeInTheDocument();
});
});
// Test 3: Affiche le lien vers /settings/sessions
it('should display link to /settings/sessions', async () => {
vi.mocked(apiClient.get).mockResolvedValue({
data: {
sessions: [],
count: 0,
},
});
render(
<TestWrapper>
<UserProfile />
2025-12-13 02:34:34 +00:00
</TestWrapper>,
);
await waitFor(() => {
const link = screen.getByText('Manage Sessions').closest('a');
expect(link).toBeInTheDocument();
expect(link).toHaveAttribute('href', '/settings/sessions');
});
});
// Test 4: Gère les erreurs de récupération
it('should handle fetch errors gracefully', async () => {
vi.mocked(apiClient.get).mockRejectedValue({
response: {
data: {
error: 'Failed to fetch sessions',
},
},
});
render(
<TestWrapper>
<UserProfile />
2025-12-13 02:34:34 +00:00
</TestWrapper>,
);
await waitFor(() => {
// Le composant devrait toujours s'afficher même en cas d'erreur
expect(screen.getByText('Active Sessions')).toBeInTheDocument();
// Il devrait afficher 0 ou "Error" en cas d'erreur
expect(screen.getByText('Error')).toBeInTheDocument();
});
});
// Test bonus: Affiche "Loading..." pendant le chargement
it('should display loading state while fetching', () => {
vi.mocked(apiClient.get).mockImplementation(
2025-12-13 02:34:34 +00:00
() => new Promise(() => {}), // Never resolves
);
render(
<TestWrapper>
<UserProfile />
2025-12-13 02:34:34 +00:00
</TestWrapper>,
);
expect(screen.getByText('Loading...')).toBeInTheDocument();
});
});