import { Test, TestingModule } from '@nestjs/testing'; import { UnauthorizedException } from '@nestjs/common'; import axios, { AxiosInstance } from 'axios'; import { AuthService } from './auth.service'; import { LoginDto } from './dto/login.dto'; jest.mock('axios'); const mockedAxios = axios as jest.Mocked; describe('AuthService', () => { let service: AuthService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [AuthService], }).compile(); service = module.get(AuthService); jest.clearAllMocks(); }); it('should be defined', () => { expect(service).toBeDefined(); }); describe('getUrl', () => { it('should return development URL when NODE_ENV is development', () => { process.env.NODE_ENV = 'development'; expect(service['getUrl']()).toBe('https://auth.clipperia.com.br'); }); it('should return production URL when NODE_ENV is not development', () => { process.env.NODE_ENV = 'production'; expect(service['getUrl']()).toBe('http://keycloak:8080'); }); }); describe('login', () => { const loginDto: LoginDto = { username: 'testuser', password: 'testpass', }; const mockTokenResponse = { access_token: 'mock-access-token', refresh_token: 'mock-refresh-token', expires_in: 300, refresh_expires_in: 1800, }; it('should login successfully', async () => { const mockPost = jest .fn() .mockResolvedValueOnce({ data: mockTokenResponse }); mockedAxios.create.mockReturnValueOnce({ post: mockPost, } as unknown as AxiosInstance); const result = await service.login(loginDto); expect(mockPost).toHaveBeenCalledWith( '/token', expect.any(URLSearchParams), ); expect(result).toEqual(mockTokenResponse); }); it('should throw UnauthorizedException when login fails', async () => { const mockError = { isAxiosError: true, response: { status: 401, data: { error: 'invalid_grant' }, }, }; const mockPost = jest.fn().mockRejectedValueOnce(mockError); mockedAxios.create.mockReturnValueOnce({ post: mockPost, } as unknown as AxiosInstance); await expect(service.login(loginDto)).rejects.toThrow( UnauthorizedException, ); }); }); describe('logout', () => { const refreshToken = 'mock-refresh-token'; it('should logout successfully', async () => { const mockPost = jest.fn().mockResolvedValueOnce({}); mockedAxios.create.mockReturnValueOnce({ post: mockPost, } as unknown as AxiosInstance); await service.logout(refreshToken); expect(mockPost).toHaveBeenCalledWith( '/logout', expect.any(URLSearchParams), ); }); it('should throw UnauthorizedException when logout fails', async () => { const mockError = { isAxiosError: true, response: { status: 400, data: { error: 'invalid_token' }, }, }; const mockPost = jest.fn().mockRejectedValueOnce(mockError); mockedAxios.create.mockReturnValueOnce({ post: mockPost, } as unknown as AxiosInstance); await expect(service.logout(refreshToken)).rejects.toThrow( UnauthorizedException, ); }); }); describe('refreshToken', () => { const refreshToken = 'mock-refresh-token'; const mockTokenResponse = { access_token: 'new-access-token', refresh_token: 'new-refresh-token', expires_in: 300, refresh_expires_in: 1800, }; it('should refresh token successfully', async () => { const mockPost = jest .fn() .mockResolvedValueOnce({ data: mockTokenResponse }); mockedAxios.create.mockReturnValueOnce({ post: mockPost, } as unknown as AxiosInstance); const result = await service.refreshToken(refreshToken); expect(mockPost).toHaveBeenCalledWith( '/token', expect.any(URLSearchParams), ); expect(result).toEqual(mockTokenResponse); }); it('should throw UnauthorizedException when refresh token is invalid', async () => { const mockError = { isAxiosError: true, response: { status: 400, data: { error: 'invalid_grant' }, }, }; const mockPost = jest.fn().mockRejectedValueOnce(mockError); mockedAxios.create.mockReturnValueOnce({ post: mockPost, } as unknown as AxiosInstance); await expect(service.refreshToken(refreshToken)).rejects.toThrow( UnauthorizedException, ); }); }); });