150 lines
3.8 KiB
TypeScript
150 lines
3.8 KiB
TypeScript
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: [
|
|
{
|
|
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 />
|
|
</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 />
|
|
</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 />
|
|
</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 />
|
|
</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(
|
|
() => new Promise(() => {}), // Never resolves
|
|
);
|
|
|
|
render(
|
|
<TestWrapper>
|
|
<UserProfile />
|
|
</TestWrapper>,
|
|
);
|
|
|
|
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
});
|
|
});
|