|
|
@@ -1,293 +0,0 @@
|
|
|
-import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
|
-import { UserService } from '../../src/services/user.service';
|
|
|
-import { UserEntity } from '../../src/entities/user.entity';
|
|
|
-import { Role } from '../../src/entities/role.entity';
|
|
|
-import { DataSource, Repository } from 'typeorm';
|
|
|
-
|
|
|
-// Mock DataSource
|
|
|
-const mockDataSource = {
|
|
|
- getRepository: vi.fn()
|
|
|
-} as unknown as DataSource;
|
|
|
-
|
|
|
-// Mock repositories
|
|
|
-const mockUserRepository = {
|
|
|
- create: vi.fn(),
|
|
|
- save: vi.fn(),
|
|
|
- findOne: vi.fn(),
|
|
|
- update: vi.fn(),
|
|
|
- delete: vi.fn(),
|
|
|
- find: vi.fn(),
|
|
|
- findByIds: vi.fn()
|
|
|
-} as unknown as Repository<UserEntity>;
|
|
|
-
|
|
|
-const mockRoleRepository = {
|
|
|
- findByIds: vi.fn()
|
|
|
-} as unknown as Repository<Role>;
|
|
|
-
|
|
|
-describe('UserService', () => {
|
|
|
- let userService: UserService;
|
|
|
-
|
|
|
- beforeEach(() => {
|
|
|
- vi.clearAllMocks();
|
|
|
-
|
|
|
- // Setup mock repositories
|
|
|
- vi.mocked(mockDataSource.getRepository)
|
|
|
- .mockReturnValueOnce(mockUserRepository)
|
|
|
- .mockReturnValueOnce(mockRoleRepository);
|
|
|
-
|
|
|
- userService = new UserService(mockDataSource);
|
|
|
- });
|
|
|
-
|
|
|
- describe('createUser', () => {
|
|
|
- it('should create a user with hashed password', async () => {
|
|
|
- const userData = {
|
|
|
- username: 'testuser',
|
|
|
- password: 'password123',
|
|
|
- email: 'test@example.com'
|
|
|
- };
|
|
|
-
|
|
|
- const mockUser = {
|
|
|
- id: 1,
|
|
|
- ...userData,
|
|
|
- password: 'hashed_password',
|
|
|
- phone: null,
|
|
|
- nickname: null,
|
|
|
- name: null,
|
|
|
- avatarFileId: null,
|
|
|
- disabledStatus: 'enabled',
|
|
|
- deleteStatus: 'active',
|
|
|
- createdAt: new Date(),
|
|
|
- updatedAt: new Date(),
|
|
|
- roles: []
|
|
|
- } as unknown as UserEntity;
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.create).mockReturnValue(mockUser);
|
|
|
- vi.mocked(mockUserRepository.save).mockResolvedValue(mockUser);
|
|
|
-
|
|
|
- const result = await userService.createUser(userData);
|
|
|
-
|
|
|
- expect(mockUserRepository.create).toHaveBeenCalledWith({
|
|
|
- ...userData,
|
|
|
- password: expect.not.stringMatching('password123') // Password should be hashed
|
|
|
- });
|
|
|
- expect(mockUserRepository.save).toHaveBeenCalledWith(mockUser);
|
|
|
- expect(result).toEqual(mockUser);
|
|
|
- });
|
|
|
-
|
|
|
- it('should throw error when creation fails', async () => {
|
|
|
- const userData = {
|
|
|
- username: 'testuser',
|
|
|
- password: 'password123'
|
|
|
- };
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.create).mockImplementation(() => {
|
|
|
- throw new Error('Database error');
|
|
|
- });
|
|
|
-
|
|
|
- await expect(userService.createUser(userData)).rejects.toThrow('Failed to create user');
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('getUserById', () => {
|
|
|
- it('should return user by id', async () => {
|
|
|
- const mockUser = {
|
|
|
- id: 1,
|
|
|
- username: 'testuser',
|
|
|
- password: 'hashedpassword',
|
|
|
- phone: null,
|
|
|
- email: 'test@example.com',
|
|
|
- nickname: null,
|
|
|
- name: null,
|
|
|
- avatarFileId: null,
|
|
|
- disabledStatus: 'enabled',
|
|
|
- deleteStatus: 'active',
|
|
|
- createdAt: new Date(),
|
|
|
- updatedAt: new Date(),
|
|
|
- roles: []
|
|
|
- } as unknown as UserEntity;
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.findOne).mockResolvedValue(mockUser);
|
|
|
-
|
|
|
- const result = await userService.getUserById(1);
|
|
|
-
|
|
|
- expect(mockUserRepository.findOne).toHaveBeenCalledWith({
|
|
|
- where: { id: 1 },
|
|
|
- relations: ['roles', 'avatarFile']
|
|
|
- });
|
|
|
- expect(result).toEqual(mockUser);
|
|
|
- });
|
|
|
-
|
|
|
- it('should return null when user not found', async () => {
|
|
|
- vi.mocked(mockUserRepository.findOne).mockResolvedValue(null);
|
|
|
-
|
|
|
- const result = await userService.getUserById(999);
|
|
|
-
|
|
|
- expect(result).toBeNull();
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('getUserByUsername', () => {
|
|
|
- it('should return user by username', async () => {
|
|
|
- const mockUser = {
|
|
|
- id: 1,
|
|
|
- username: 'testuser',
|
|
|
- password: 'hashedpassword',
|
|
|
- phone: null,
|
|
|
- email: 'test@example.com',
|
|
|
- nickname: null,
|
|
|
- name: null,
|
|
|
- avatarFileId: null,
|
|
|
- disabledStatus: 'enabled',
|
|
|
- deleteStatus: 'active',
|
|
|
- createdAt: new Date(),
|
|
|
- updatedAt: new Date(),
|
|
|
- roles: []
|
|
|
- } as unknown as UserEntity;
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.findOne).mockResolvedValue(mockUser);
|
|
|
-
|
|
|
- const result = await userService.getUserByUsername('testuser');
|
|
|
-
|
|
|
- expect(mockUserRepository.findOne).toHaveBeenCalledWith({
|
|
|
- where: { username: 'testuser' },
|
|
|
- relations: ['roles', 'avatarFile']
|
|
|
- });
|
|
|
- expect(result).toEqual(mockUser);
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('updateUser', () => {
|
|
|
- it('should update user with hashed password', async () => {
|
|
|
- const updateData = {
|
|
|
- password: 'newpassword',
|
|
|
- email: 'new@example.com'
|
|
|
- };
|
|
|
-
|
|
|
- const updatedUser = {
|
|
|
- id: 1,
|
|
|
- username: 'testuser',
|
|
|
- password: 'hashed_newpassword',
|
|
|
- email: 'new@example.com',
|
|
|
- roles: []
|
|
|
- } as unknown as UserEntity;
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.update).mockResolvedValue({ affected: 1 } as any);
|
|
|
- vi.mocked(mockUserRepository.findOne).mockResolvedValue(updatedUser);
|
|
|
-
|
|
|
- const result = await userService.updateUser(1, updateData);
|
|
|
-
|
|
|
- expect(mockUserRepository.update).toHaveBeenCalledWith(1, {
|
|
|
- ...updateData,
|
|
|
- password: expect.not.stringMatching('newpassword') // Password should be hashed
|
|
|
- });
|
|
|
- expect(result).toEqual(updatedUser);
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('deleteUser', () => {
|
|
|
- it('should delete user successfully', async () => {
|
|
|
- vi.mocked(mockUserRepository.delete).mockResolvedValue({ affected: 1 } as any);
|
|
|
-
|
|
|
- const result = await userService.deleteUser(1);
|
|
|
-
|
|
|
- expect(mockUserRepository.delete).toHaveBeenCalledWith(1);
|
|
|
- expect(result).toBe(true);
|
|
|
- });
|
|
|
-
|
|
|
- it('should return false when user not found', async () => {
|
|
|
- vi.mocked(mockUserRepository.delete).mockResolvedValue({ affected: 0 } as any);
|
|
|
-
|
|
|
- const result = await userService.deleteUser(999);
|
|
|
-
|
|
|
- expect(result).toBe(false);
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('assignRoles', () => {
|
|
|
- it('should assign roles to user', async () => {
|
|
|
- const mockUser = {
|
|
|
- id: 1,
|
|
|
- username: 'testuser',
|
|
|
- password: 'hashedpassword',
|
|
|
- phone: null,
|
|
|
- email: 'test@example.com',
|
|
|
- nickname: null,
|
|
|
- name: null,
|
|
|
- avatarFileId: null,
|
|
|
- disabledStatus: 'enabled',
|
|
|
- deleteStatus: 'active',
|
|
|
- createdAt: new Date(),
|
|
|
- updatedAt: new Date(),
|
|
|
- roles: []
|
|
|
- } as unknown as UserEntity;
|
|
|
-
|
|
|
- const mockRoles = [
|
|
|
- { id: 1, name: 'admin' } as Role,
|
|
|
- { id: 2, name: 'user' } as Role
|
|
|
- ];
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.findOne).mockResolvedValue(mockUser);
|
|
|
- vi.mocked(mockRoleRepository.findByIds).mockResolvedValue(mockRoles);
|
|
|
- vi.mocked(mockUserRepository.save).mockResolvedValue({
|
|
|
- ...mockUser,
|
|
|
- roles: mockRoles
|
|
|
- } as UserEntity);
|
|
|
-
|
|
|
- const result = await userService.assignRoles(1, [1, 2]);
|
|
|
-
|
|
|
- expect(mockRoleRepository.findByIds).toHaveBeenCalledWith([1, 2]);
|
|
|
- expect(mockUserRepository.save).toHaveBeenCalledWith({
|
|
|
- ...mockUser,
|
|
|
- roles: mockRoles
|
|
|
- });
|
|
|
- expect(result?.roles).toEqual(mockRoles);
|
|
|
- });
|
|
|
-
|
|
|
- it('should return null when user not found', async () => {
|
|
|
- vi.mocked(mockUserRepository.findOne).mockResolvedValue(null);
|
|
|
-
|
|
|
- const result = await userService.assignRoles(999, [1, 2]);
|
|
|
-
|
|
|
- expect(result).toBeNull();
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('getUsers', () => {
|
|
|
- it('should return all users', async () => {
|
|
|
- const mockUsers = [
|
|
|
- { id: 1, username: 'user1', roles: [] },
|
|
|
- { id: 2, username: 'user2', roles: [] }
|
|
|
- ] as unknown as UserEntity[];
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.find).mockResolvedValue(mockUsers);
|
|
|
-
|
|
|
- const result = await userService.getUsers();
|
|
|
-
|
|
|
- expect(mockUserRepository.find).toHaveBeenCalledWith({
|
|
|
- relations: ['roles', 'avatarFile']
|
|
|
- });
|
|
|
- expect(result).toEqual(mockUsers);
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('getUserByAccount', () => {
|
|
|
- it('should return user by username or email', async () => {
|
|
|
- const mockUser = {
|
|
|
- id: 1,
|
|
|
- username: 'testuser',
|
|
|
- email: 'test@example.com',
|
|
|
- roles: []
|
|
|
- } as unknown as UserEntity;
|
|
|
-
|
|
|
- vi.mocked(mockUserRepository.findOne).mockResolvedValue(mockUser);
|
|
|
-
|
|
|
- const result = await userService.getUserByAccount('testuser');
|
|
|
-
|
|
|
- expect(mockUserRepository.findOne).toHaveBeenCalledWith({
|
|
|
- where: [{ username: 'testuser' }, { email: 'testuser' }],
|
|
|
- relations: ['roles', 'avatarFile']
|
|
|
- });
|
|
|
- expect(result).toEqual(mockUser);
|
|
|
- });
|
|
|
- });
|
|
|
-});
|