Files
clipperia-api/src/modules/auth/auth.service.spec.ts

177 lines
4.7 KiB
TypeScript

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<typeof axios>;
describe('AuthService', () => {
let service: AuthService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AuthService],
}).compile();
service = module.get<AuthService>(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,
);
});
});
});