the-tip-top-frontend/__tests__/services/auth.service.test.ts
soufiane 0a00c04b54 fix: reduce code duplication and add tests for SonarQube quality gate
- Consolidate API logic: hooks/useApi.ts now uses services/api.ts
- Create BaseFormField component to reduce form duplication
- Refactor FormField, FormSelect, FormTextarea to use BaseFormField
- Add centralized theme utility (utils/theme.ts) for colors/styles
- Add comprehensive tests for api, auth.service, useApi hooks, AuthContext
- Add tests for theme utility

This reduces duplication from 11.45% and improves test coverage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 14:54:24 +01:00

277 lines
7.1 KiB
TypeScript

/**
* Tests for the Auth Service
* @jest-environment jsdom
*/
import { authService } from '@/services/auth.service';
import { api } from '@/services/api';
import { API_ENDPOINTS } from '@/utils/constants';
// Mock the api module
jest.mock('@/services/api', () => ({
api: {
get: jest.fn(),
post: jest.fn(),
put: jest.fn(),
patch: jest.fn(),
delete: jest.fn(),
},
ApiError: class ApiError extends Error {
constructor(public status: number, message: string, public data?: unknown) {
super(message);
this.name = 'ApiError';
}
},
}));
describe('Auth Service', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('login', () => {
it('should login with valid credentials', async () => {
const mockResponse = {
success: true,
token: 'jwt-token-123',
user: {
id: '1',
email: 'test@test.com',
firstName: 'John',
lastName: 'Doe',
role: 'CLIENT',
},
};
(api.post as jest.Mock).mockResolvedValueOnce(mockResponse);
const result = await authService.login({
email: 'test@test.com',
password: 'password123',
});
expect(api.post).toHaveBeenCalledWith(
API_ENDPOINTS.AUTH.LOGIN,
{ email: 'test@test.com', password: 'password123' }
);
expect(result).toEqual({
token: 'jwt-token-123',
user: mockResponse.user,
});
});
it('should throw error on invalid credentials', async () => {
(api.post as jest.Mock).mockRejectedValueOnce(new Error('Invalid credentials'));
await expect(
authService.login({ email: 'test@test.com', password: 'wrong' })
).rejects.toThrow('Invalid credentials');
});
});
describe('register', () => {
it('should register a new user', async () => {
const mockResponse = {
success: true,
token: 'jwt-token-new',
user: {
id: '2',
email: 'new@test.com',
firstName: 'Jane',
lastName: 'Doe',
role: 'CLIENT',
},
};
(api.post as jest.Mock).mockResolvedValueOnce(mockResponse);
const registerData = {
email: 'new@test.com',
password: 'password123',
firstName: 'Jane',
lastName: 'Doe',
};
const result = await authService.register(registerData);
expect(api.post).toHaveBeenCalledWith(
API_ENDPOINTS.AUTH.REGISTER,
registerData
);
expect(result.token).toBe('jwt-token-new');
expect(result.user.email).toBe('new@test.com');
});
it('should throw error if email already exists', async () => {
(api.post as jest.Mock).mockRejectedValueOnce(new Error('Email already exists'));
await expect(
authService.register({
email: 'existing@test.com',
password: 'password',
firstName: 'Test',
lastName: 'User',
})
).rejects.toThrow('Email already exists');
});
});
describe('logout', () => {
it('should call logout endpoint', async () => {
(api.post as jest.Mock).mockResolvedValueOnce({ success: true });
await authService.logout();
expect(api.post).toHaveBeenCalledWith(API_ENDPOINTS.AUTH.LOGOUT);
});
});
describe('getCurrentUser', () => {
it('should return user data from response.data', async () => {
const mockUser = {
id: '1',
email: 'test@test.com',
firstName: 'John',
lastName: 'Doe',
role: 'CLIENT',
};
(api.get as jest.Mock).mockResolvedValueOnce({
success: true,
data: mockUser,
});
const result = await authService.getCurrentUser();
expect(api.get).toHaveBeenCalledWith(API_ENDPOINTS.AUTH.ME);
expect(result).toEqual(mockUser);
});
it('should return user data from response.user', async () => {
const mockUser = {
id: '1',
email: 'test@test.com',
firstName: 'John',
lastName: 'Doe',
role: 'CLIENT',
};
(api.get as jest.Mock).mockResolvedValueOnce({
success: true,
user: mockUser,
});
const result = await authService.getCurrentUser();
expect(result).toEqual(mockUser);
});
it('should return response directly if no data or user field', async () => {
const mockUser = {
id: '1',
email: 'test@test.com',
firstName: 'John',
lastName: 'Doe',
role: 'CLIENT',
};
(api.get as jest.Mock).mockResolvedValueOnce(mockUser);
const result = await authService.getCurrentUser();
expect(result).toEqual(mockUser);
});
});
describe('googleLogin', () => {
it('should login with Google token', async () => {
const mockResponse = {
success: true,
token: 'jwt-google-token',
user: {
id: '3',
email: 'google@test.com',
firstName: 'Google',
lastName: 'User',
role: 'CLIENT',
},
};
(api.post as jest.Mock).mockResolvedValueOnce(mockResponse);
const result = await authService.googleLogin('google-oauth-token');
expect(api.post).toHaveBeenCalledWith(
API_ENDPOINTS.AUTH.GOOGLE,
{ token: 'google-oauth-token' }
);
expect(result.token).toBe('jwt-google-token');
});
});
describe('facebookLogin', () => {
it('should login with Facebook token', async () => {
const mockResponse = {
success: true,
token: 'jwt-facebook-token',
user: {
id: '4',
email: 'facebook@test.com',
firstName: 'Facebook',
lastName: 'User',
role: 'CLIENT',
},
};
(api.post as jest.Mock).mockResolvedValueOnce(mockResponse);
const result = await authService.facebookLogin('facebook-oauth-token');
expect(api.post).toHaveBeenCalledWith(
API_ENDPOINTS.AUTH.FACEBOOK,
{ token: 'facebook-oauth-token' }
);
expect(result.token).toBe('jwt-facebook-token');
});
});
describe('verifyEmail', () => {
it('should verify email with token', async () => {
(api.post as jest.Mock).mockResolvedValueOnce({ success: true });
await authService.verifyEmail('verification-token');
expect(api.post).toHaveBeenCalledWith(
API_ENDPOINTS.AUTH.VERIFY_EMAIL,
{ token: 'verification-token' }
);
});
});
describe('forgotPassword', () => {
it('should send forgot password request', async () => {
(api.post as jest.Mock).mockResolvedValueOnce({ success: true });
await authService.forgotPassword('test@test.com');
expect(api.post).toHaveBeenCalledWith(
API_ENDPOINTS.AUTH.FORGOT_PASSWORD,
{ email: 'test@test.com' }
);
});
});
describe('resetPassword', () => {
it('should reset password with token', async () => {
(api.post as jest.Mock).mockResolvedValueOnce({ success: true });
await authService.resetPassword('reset-token', 'newPassword123');
expect(api.post).toHaveBeenCalledWith(
API_ENDPOINTS.AUTH.RESET_PASSWORD,
{ token: 'reset-token', password: 'newPassword123' }
);
});
});
});