test: Ajouter les tests unitaires manquants (backend et frontend)
Couverture des processors (RefreshToken, RequestPasswordReset, ResetPassword, SwitchRole, UpdateUserRoles), des query handlers (HasGradesInPeriod, HasStudentsInClass), des messaging handlers (SendActivationConfirmation, SendPasswordResetEmail), et côté frontend des modules auth, roles, monitoring, types et E2E tokens.
This commit is contained in:
178
frontend/tests/unit/lib/features/roles/api/roles.test.ts
Normal file
178
frontend/tests/unit/lib/features/roles/api/roles.test.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
|
||||
/**
|
||||
* Unit tests for the roles API module.
|
||||
*
|
||||
* Tests getMyRoles(), switchRole(), and updateUserRoles() which all rely on
|
||||
* authenticatedFetch from $lib/auth and getApiBaseUrl from $lib/api.
|
||||
*/
|
||||
|
||||
// Mock $lib/api
|
||||
vi.mock('$lib/api', () => ({
|
||||
getApiBaseUrl: () => 'http://test.classeo.local:18000/api'
|
||||
}));
|
||||
|
||||
// Mock $lib/auth - authenticatedFetch is the primary dependency
|
||||
const mockAuthenticatedFetch = vi.fn();
|
||||
vi.mock('$lib/auth', () => ({
|
||||
authenticatedFetch: (...args: unknown[]) => mockAuthenticatedFetch(...args)
|
||||
}));
|
||||
|
||||
import { getMyRoles, switchRole, updateUserRoles } from '$lib/features/roles/api/roles';
|
||||
|
||||
describe('roles API', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// getMyRoles
|
||||
// ==========================================================================
|
||||
describe('getMyRoles', () => {
|
||||
it('should return roles array and activeRole on success', async () => {
|
||||
const mockResponse = {
|
||||
roles: [
|
||||
{ value: 'ROLE_ADMIN', label: 'Administrateur' },
|
||||
{ value: 'ROLE_TEACHER', label: 'Enseignant' }
|
||||
],
|
||||
activeRole: 'ROLE_ADMIN',
|
||||
activeRoleLabel: 'Administrateur'
|
||||
};
|
||||
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: () => Promise.resolve(mockResponse)
|
||||
});
|
||||
|
||||
const result = await getMyRoles();
|
||||
|
||||
expect(mockAuthenticatedFetch).toHaveBeenCalledWith(
|
||||
'http://test.classeo.local:18000/api/me/roles'
|
||||
);
|
||||
expect(result.roles).toHaveLength(2);
|
||||
expect(result.roles[0]).toEqual({ value: 'ROLE_ADMIN', label: 'Administrateur' });
|
||||
expect(result.activeRole).toBe('ROLE_ADMIN');
|
||||
expect(result.activeRoleLabel).toBe('Administrateur');
|
||||
});
|
||||
|
||||
it('should throw Error when the API response is not ok', async () => {
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 500
|
||||
});
|
||||
|
||||
await expect(getMyRoles()).rejects.toThrow('Failed to fetch roles');
|
||||
});
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// switchRole
|
||||
// ==========================================================================
|
||||
describe('switchRole', () => {
|
||||
it('should return new activeRole on success', async () => {
|
||||
const mockResponse = {
|
||||
activeRole: 'ROLE_TEACHER',
|
||||
activeRoleLabel: 'Enseignant'
|
||||
};
|
||||
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: () => Promise.resolve(mockResponse)
|
||||
});
|
||||
|
||||
const result = await switchRole('ROLE_TEACHER');
|
||||
|
||||
expect(mockAuthenticatedFetch).toHaveBeenCalledWith(
|
||||
'http://test.classeo.local:18000/api/me/switch-role',
|
||||
expect.objectContaining({
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ role: 'ROLE_TEACHER' })
|
||||
})
|
||||
);
|
||||
expect(result.activeRole).toBe('ROLE_TEACHER');
|
||||
expect(result.activeRoleLabel).toBe('Enseignant');
|
||||
});
|
||||
|
||||
it('should throw Error when the API response is not ok', async () => {
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 400
|
||||
});
|
||||
|
||||
await expect(switchRole('ROLE_INVALID')).rejects.toThrow('Failed to switch role');
|
||||
});
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// updateUserRoles
|
||||
// ==========================================================================
|
||||
describe('updateUserRoles', () => {
|
||||
it('should complete without error on 2xx success', async () => {
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
status: 204
|
||||
});
|
||||
|
||||
// Should resolve without throwing
|
||||
await expect(
|
||||
updateUserRoles('user-uuid-123', ['ROLE_ADMIN', 'ROLE_TEACHER'])
|
||||
).resolves.toBeUndefined();
|
||||
|
||||
expect(mockAuthenticatedFetch).toHaveBeenCalledWith(
|
||||
'http://test.classeo.local:18000/api/users/user-uuid-123/roles',
|
||||
expect.objectContaining({
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ roles: ['ROLE_ADMIN', 'ROLE_TEACHER'] })
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw with hydra:description when present in error response', async () => {
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 422,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
'hydra:description': 'Le rôle ROLE_INVALID est inconnu.'
|
||||
})
|
||||
});
|
||||
|
||||
await expect(
|
||||
updateUserRoles('user-uuid-123', ['ROLE_INVALID'])
|
||||
).rejects.toThrow('Le rôle ROLE_INVALID est inconnu.');
|
||||
});
|
||||
|
||||
it('should throw with detail when present in error response', async () => {
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 403,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
detail: 'Accès refusé.'
|
||||
})
|
||||
});
|
||||
|
||||
await expect(
|
||||
updateUserRoles('user-uuid-123', ['ROLE_ADMIN'])
|
||||
).rejects.toThrow('Accès refusé.');
|
||||
});
|
||||
|
||||
it('should throw generic message when error body is not valid JSON', async () => {
|
||||
mockAuthenticatedFetch.mockResolvedValueOnce({
|
||||
ok: false,
|
||||
status: 500,
|
||||
json: () => Promise.reject(new Error('Unexpected token'))
|
||||
});
|
||||
|
||||
await expect(
|
||||
updateUserRoles('user-uuid-123', ['ROLE_ADMIN'])
|
||||
).rejects.toThrow('Erreur lors de la mise à jour des rôles (500)');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user