template-saas/apps/backend/dist/modules/users/__tests__/users.service.spec.js
rckrdmrd 50a821a415
Some checks failed
CI / Backend CI (push) Has been cancelled
CI / Frontend CI (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / CI Summary (push) Has been cancelled
[SIMCO-V38] feat: Actualizar a SIMCO v3.8.0
- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8
- Actualizaciones de configuracion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 08:53:08 -06:00

176 lines
8.0 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const testing_1 = require("@nestjs/testing");
const typeorm_1 = require("@nestjs/typeorm");
const common_1 = require("@nestjs/common");
const users_service_1 = require("../users.service");
const user_entity_1 = require("../../auth/entities/user.entity");
describe('UsersService', () => {
let service;
let userRepository;
const mockUser = {
id: 'user-123',
tenant_id: 'tenant-123',
email: 'test@example.com',
password_hash: 'hashed_password',
first_name: 'John',
last_name: 'Doe',
avatar_url: 'https://example.com/avatar.png',
phone: '+1234567890',
status: 'active',
email_verified: true,
email_verified_at: new Date('2026-01-01'),
last_login_at: new Date('2026-01-07'),
last_login_ip: '192.168.1.1',
metadata: { preferences: { theme: 'dark' } },
created_at: new Date('2026-01-01'),
updated_at: new Date('2026-01-07'),
get fullName() {
return [this.first_name, this.last_name].filter(Boolean).join(' ');
},
};
beforeEach(async () => {
const module = await testing_1.Test.createTestingModule({
providers: [
users_service_1.UsersService,
{
provide: (0, typeorm_1.getRepositoryToken)(user_entity_1.User),
useValue: {
findOne: jest.fn(),
find: jest.fn(),
findAndCount: jest.fn(),
save: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
},
},
],
}).compile();
service = module.get(users_service_1.UsersService);
userRepository = module.get((0, typeorm_1.getRepositoryToken)(user_entity_1.User));
});
afterEach(() => {
jest.clearAllMocks();
});
describe('findAllByTenant', () => {
it('should return paginated users for a tenant', async () => {
const users = [mockUser];
userRepository.findAndCount.mockResolvedValue([users, 1]);
const result = await service.findAllByTenant('tenant-123', 1, 10);
expect(result).toEqual({
data: [expect.objectContaining({ id: 'user-123' })],
total: 1,
page: 1,
limit: 10,
});
expect(userRepository.findAndCount).toHaveBeenCalledWith({
where: { tenant_id: 'tenant-123' },
skip: 0,
take: 10,
order: { created_at: 'DESC' },
});
});
it('should return sanitized users without password_hash', async () => {
userRepository.findAndCount.mockResolvedValue([[mockUser], 1]);
const result = await service.findAllByTenant('tenant-123', 1, 10);
expect(result.data[0]).not.toHaveProperty('password_hash');
expect(result.data[0]).toHaveProperty('email');
});
it('should handle pagination correctly', async () => {
userRepository.findAndCount.mockResolvedValue([[], 0]);
await service.findAllByTenant('tenant-123', 2, 20);
expect(userRepository.findAndCount).toHaveBeenCalledWith({
where: { tenant_id: 'tenant-123' },
skip: 20,
take: 20,
order: { created_at: 'DESC' },
});
});
it('should return empty array when no users found', async () => {
userRepository.findAndCount.mockResolvedValue([[], 0]);
const result = await service.findAllByTenant('tenant-123', 1, 10);
expect(result.data).toEqual([]);
expect(result.total).toBe(0);
});
});
describe('findOne', () => {
it('should return a user by id and tenant', async () => {
userRepository.findOne.mockResolvedValue(mockUser);
const result = await service.findOne('user-123', 'tenant-123');
expect(result).not.toHaveProperty('password_hash');
expect(result).toHaveProperty('email', 'test@example.com');
expect(userRepository.findOne).toHaveBeenCalledWith({
where: { id: 'user-123', tenant_id: 'tenant-123' },
});
});
it('should throw NotFoundException if user not found', async () => {
userRepository.findOne.mockResolvedValue(null);
await expect(service.findOne('non-existent', 'tenant-123')).rejects.toThrow(common_1.NotFoundException);
});
it('should not return user from different tenant', async () => {
userRepository.findOne.mockResolvedValue(null);
await expect(service.findOne('user-123', 'different-tenant')).rejects.toThrow(common_1.NotFoundException);
expect(userRepository.findOne).toHaveBeenCalledWith({
where: { id: 'user-123', tenant_id: 'different-tenant' },
});
});
});
describe('update', () => {
it('should update allowed user fields', async () => {
const userCopy = { ...mockUser };
userRepository.findOne.mockResolvedValue(userCopy);
userRepository.save.mockResolvedValue(userCopy);
const updateDto = {
first_name: 'Jane',
last_name: 'Smith',
};
const result = await service.update('user-123', updateDto, 'tenant-123');
expect(userRepository.save).toHaveBeenCalled();
expect(result).not.toHaveProperty('password_hash');
});
it('should throw NotFoundException if user not found', async () => {
userRepository.findOne.mockResolvedValue(null);
await expect(service.update('non-existent', { first_name: 'Test' }, 'tenant-123')).rejects.toThrow(common_1.NotFoundException);
});
it('should only update allowed fields', async () => {
const userCopy = { ...mockUser };
userRepository.findOne.mockResolvedValue(userCopy);
userRepository.save.mockResolvedValue(userCopy);
const updateDto = {
first_name: 'Jane',
email: 'hacker@example.com',
password_hash: 'new_hash',
};
await service.update('user-123', updateDto, 'tenant-123');
const savedUser = userRepository.save.mock.calls[0][0];
expect(savedUser.email).not.toBe('hacker@example.com');
});
it('should update phone number', async () => {
const userCopy = { ...mockUser };
userRepository.findOne.mockResolvedValue(userCopy);
userRepository.save.mockResolvedValue(userCopy);
await service.update('user-123', { phone: '+9876543210' }, 'tenant-123');
const savedUser = userRepository.save.mock.calls[0][0];
expect(savedUser.phone).toBe('+9876543210');
});
it('should update avatar_url', async () => {
const userCopy = { ...mockUser };
userRepository.findOne.mockResolvedValue(userCopy);
userRepository.save.mockResolvedValue(userCopy);
await service.update('user-123', { avatar_url: 'https://new-avatar.com/img.png' }, 'tenant-123');
const savedUser = userRepository.save.mock.calls[0][0];
expect(savedUser.avatar_url).toBe('https://new-avatar.com/img.png');
});
it('should update metadata', async () => {
const userCopy = { ...mockUser };
userRepository.findOne.mockResolvedValue(userCopy);
userRepository.save.mockResolvedValue(userCopy);
const newMetadata = { preferences: { language: 'es' } };
await service.update('user-123', { metadata: newMetadata }, 'tenant-123');
const savedUser = userRepository.save.mock.calls[0][0];
expect(savedUser.metadata).toEqual(newMetadata);
});
});
});
//# sourceMappingURL=users.service.spec.js.map