fastcheck/src/services/__tests__/api.test.ts
2026-04-08 13:58:46 -04:00

282 lines
8.8 KiB
TypeScript

import axios from 'axios';
import { apiClient, fakeAuthApi, validateChileanRut, formatChileanRut, setupMonitoring } from '../api';
import { LoginCredentials } from '../../types/auth';
import logger from '../../utils/logger';
// Mock axios
jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;
// Mock localStorage
const mockLocalStorage = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn()
};
Object.defineProperty(window, 'localStorage', {
value: mockLocalStorage
});
// Mock console methods
const originalConsole = console;
beforeAll(() => {
logger.log = jest.fn();
logger.error = jest.fn();
});
afterAll(() => {
logger.log = originallogger.log;
logger.error = originallogger.error;
});
describe('API Service', () => {
beforeEach(() => {
jest.clearAllMocks();
mockLocalStorage.getItem.mockReturnValue('mock-token');
});
describe('apiClient configuration', () => {
it('should create axios instance with correct base URL', () => {
expect(apiClient.defaults.baseURL).toBeDefined();
});
it('should have request interceptor configured', () => {
expect(apiClient.interceptors.request).toBeDefined();
});
it('should have response interceptor configured in development', () => {
expect(apiClient.interceptors.response).toBeDefined();
});
});
describe('fakeAuthApi', () => {
describe('login', () => {
it('should successfully login with valid credentials', async () => {
const credentials: LoginCredentials = {
email: 'admin@example.com',
password: 'password123'
};
const result = await fakeAuthApi.login(credentials);
expect(result).toEqual({
id: '1',
email: 'admin@example.com',
name: 'Admin User',
role: 'superuser',
defaultTenantId: 'tenant-1',
tenants: ['tenant-1', 'tenant-2']
});
});
it('should throw error for invalid credentials', async () => {
const credentials: LoginCredentials = {
email: 'invalid@example.com',
password: 'wrongpassword'
};
await expect(fakeAuthApi.login(credentials))
.rejects.toThrow('Invalid email or password');
});
it('should throw error for missing email', async () => {
const credentials: LoginCredentials = {
email: '',
password: 'password123'
};
await expect(fakeAuthApi.login(credentials))
.rejects.toThrow('Email and password are required');
});
it('should throw error for missing password', async () => {
const credentials: LoginCredentials = {
email: 'admin@example.com',
password: ''
};
await expect(fakeAuthApi.login(credentials))
.rejects.toThrow('Email and password are required');
});
});
describe('register', () => {
it('should successfully register new user', async () => {
const registerData = {
email: 'newuser@example.com',
password: 'password123',
name: 'New User',
companyName: 'New Company'
};
const result = await fakeAuthApi.register(registerData);
expect(result).toEqual({
id: expect.any(String),
email: 'newuser@example.com',
name: 'New User',
role: 'user',
defaultTenantId: null,
tenants: []
});
});
it('should throw error for existing email', async () => {
const registerData = {
email: 'admin@example.com',
password: 'password123',
name: 'Admin User',
companyName: 'Admin Company'
};
await expect(fakeAuthApi.register(registerData))
.rejects.toThrow('User with this email already exists');
});
it('should throw error for missing company name', async () => {
const registerData = {
email: 'newuser@example.com',
password: 'password123',
name: 'New User',
companyName: ''
};
await expect(fakeAuthApi.register(registerData))
.rejects.toThrow('All fields are required');
});
});
});
describe('validateChileanRut', () => {
it('should validate correct RUT with dash', () => {
expect(validateChileanRut('12345678-5')).toBe(true);
expect(validateChileanRut('11111111-1')).toBe(true);
});
it('should validate correct RUT without dash', () => {
expect(validateChileanRut('123456785')).toBe(true);
expect(validateChileanRut('111111111')).toBe(true);
});
it('should validate RUT with K verification digit', () => {
expect(validateChileanRut('12345678-K')).toBe(true);
expect(validateChileanRut('12345678K')).toBe(true);
});
it('should reject invalid RUT format', () => {
expect(validateChileanRut('invalid-rut')).toBe(false);
expect(validateChileanRut('123')).toBe(false);
expect(validateChileanRut('')).toBe(false);
});
it('should reject RUT with incorrect verification digit', () => {
expect(validateChileanRut('12345678-9')).toBe(false);
expect(validateChileanRut('11111111-2')).toBe(false);
});
it('should handle null and undefined input', () => {
expect(validateChileanRut(null as any)).toBe(false);
expect(validateChileanRut(undefined as any)).toBe(false);
});
});
describe('formatChileanRut', () => {
it('should format RUT with dots and dash', () => {
expect(formatChileanRut('123456785')).toBe('12.345.678-5');
expect(formatChileanRut('111111111')).toBe('11.111.111-1');
});
it('should format RUT with K verification digit', () => {
expect(formatChileanRut('12345678K')).toBe('12.345.678-K');
expect(formatChileanRut('12345678-K')).toBe('12.345.678-K');
});
it('should handle already formatted RUT', () => {
expect(formatChileanRut('12.345.678-5')).toBe('12.345.678-5');
});
it('should handle RUT with spaces', () => {
expect(formatChileanRut(' 12345678 5 ')).toBe('12.345.678-5');
});
it('should return empty string for invalid input', () => {
expect(formatChileanRut('')).toBe('');
expect(formatChileanRut('invalid')).toBe('invalid');
});
it('should handle null and undefined input', () => {
expect(formatChileanRut(null as any)).toBe('');
expect(formatChileanRut(undefined as any)).toBe('');
});
});
describe('setupMonitoring', () => {
beforeEach(() => {
mockedAxios.post = jest.fn();
jest.mocked(axios.isAxiosError).mockImplementation(() => false);
});
it('should successfully setup monitoring', async () => {
const mockResponse = {
data: { message: 'Monitoring setup successfully' }
};
mockedAxios.post.mockResolvedValue(mockResponse);
const data = { rut: '12345678-5', frequency: 'daily' };
const result = await setupMonitoring(data);
expect(mockedAxios.post).toHaveBeenCalledWith('/monitoring', data);
expect(result).toEqual({ message: 'Monitoring setup successfully' });
});
it('should handle API errors with custom message', async () => {
const mockError = {
response: {
data: { message: 'Custom error message' }
}
};
mockedAxios.post.mockRejectedValue(mockError);
mockedAxios.isAxiosError.mockReturnValue(true);
const data = { rut: '12345678-5', frequency: 'daily' };
await expect(setupMonitoring(data))
.rejects.toThrow('Custom error message');
});
it('should handle API errors without custom message', async () => {
const mockError = {
response: {
data: {}
}
};
mockedAxios.post.mockRejectedValue(mockError);
mockedAxios.isAxiosError.mockReturnValue(true);
const data = { rut: '12345678-5', frequency: 'daily' };
await expect(setupMonitoring(data))
.rejects.toThrow('Failed to setup monitoring');
});
it('should handle network errors', async () => {
const networkError = new Error('Network Error');
mockedAxios.post.mockRejectedValue(networkError);
mockedAxios.isAxiosError.mockReturnValue(false);
const data = { rut: '12345678-5', frequency: 'daily' };
await expect(setupMonitoring(data))
.rejects.toThrow('Failed to setup monitoring due to an unexpected error.');
});
it('should validate required data fields', async () => {
const invalidData = { rut: '', frequency: 'daily' };
// This would depend on the actual implementation validation
// For now, we'll test that the function calls the API
mockedAxios.post.mockResolvedValue({ data: { message: 'Success' } });
await setupMonitoring(invalidData);
expect(mockedAxios.post).toHaveBeenCalledWith('/monitoring', invalidData);
});
});
});