299 lines
9.2 KiB
TypeScript
299 lines
9.2 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import { prisma } from '../db.server';
|
|
import { getUsers, createUser, updateUser, deleteUser, toggleUserStatus } from '../user-management.server';
|
|
import { hashPassword } from '../auth.server';
|
|
import { AUTH_LEVELS, USER_STATUS } from '~/types/auth';
|
|
|
|
describe('User Management', () => {
|
|
beforeEach(async () => {
|
|
// Clean up test data
|
|
await prisma.user.deleteMany({
|
|
where: {
|
|
email: {
|
|
contains: 'test'
|
|
}
|
|
}
|
|
});
|
|
|
|
// Ensure the main superadmin exists for login functionality
|
|
const existingSuperadmin = await prisma.user.findUnique({
|
|
where: { username: 'superadmin' }
|
|
});
|
|
|
|
if (!existingSuperadmin) {
|
|
const hashedPassword = await hashPassword('admin123');
|
|
await prisma.user.create({
|
|
data: {
|
|
name: 'Super Administrator',
|
|
username: 'superadmin',
|
|
email: 'admin@carmaintenance.com',
|
|
password: hashedPassword,
|
|
status: USER_STATUS.ACTIVE,
|
|
authLevel: AUTH_LEVELS.SUPERADMIN,
|
|
},
|
|
});
|
|
}
|
|
});
|
|
|
|
afterEach(async () => {
|
|
// Clean up test data but preserve the main superadmin
|
|
await prisma.user.deleteMany({
|
|
where: {
|
|
AND: [
|
|
{
|
|
email: {
|
|
contains: 'test'
|
|
}
|
|
},
|
|
{
|
|
username: {
|
|
not: 'superadmin'
|
|
}
|
|
}
|
|
]
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('getUsers', () => {
|
|
it('should return users with role-based filtering', async () => {
|
|
// Create test users with properly hashed passwords
|
|
const hashedPassword = await hashPassword('testpassword123');
|
|
|
|
const superadmin = await prisma.user.create({
|
|
data: {
|
|
name: 'Test Superadmin',
|
|
username: 'testsuperadmin',
|
|
email: 'testsuperadmin@example.com',
|
|
password: hashedPassword,
|
|
authLevel: AUTH_LEVELS.SUPERADMIN,
|
|
status: USER_STATUS.ACTIVE,
|
|
}
|
|
});
|
|
|
|
const admin = await prisma.user.create({
|
|
data: {
|
|
name: 'Test Admin',
|
|
username: 'testadmin',
|
|
email: 'testadmin@example.com',
|
|
password: hashedPassword,
|
|
authLevel: AUTH_LEVELS.ADMIN,
|
|
status: USER_STATUS.ACTIVE,
|
|
}
|
|
});
|
|
|
|
// Superadmin should see all users
|
|
const superadminResult = await getUsers(AUTH_LEVELS.SUPERADMIN);
|
|
expect(superadminResult.users.length).toBeGreaterThanOrEqual(2);
|
|
|
|
// Admin should not see superadmin users
|
|
const adminResult = await getUsers(AUTH_LEVELS.ADMIN);
|
|
const adminVisibleUsers = adminResult.users.filter(u => u.authLevel === AUTH_LEVELS.SUPERADMIN);
|
|
expect(adminVisibleUsers.length).toBe(0);
|
|
});
|
|
|
|
it('should support search functionality', async () => {
|
|
const hashedPassword = await hashPassword('testpassword123');
|
|
|
|
await prisma.user.create({
|
|
data: {
|
|
name: 'John Test User',
|
|
username: 'johntestuser',
|
|
email: 'johntest@example.com',
|
|
password: hashedPassword,
|
|
authLevel: AUTH_LEVELS.USER,
|
|
status: USER_STATUS.ACTIVE,
|
|
}
|
|
});
|
|
|
|
const result = await getUsers(AUTH_LEVELS.SUPERADMIN, 'John');
|
|
expect(result.users.some(u => u.name.includes('John'))).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('createUser', () => {
|
|
it('should create a new user successfully', async () => {
|
|
const userData = {
|
|
name: 'New Test User',
|
|
username: 'newtestuser',
|
|
email: 'newtest@example.com',
|
|
password: 'password123',
|
|
authLevel: AUTH_LEVELS.USER,
|
|
status: USER_STATUS.ACTIVE,
|
|
};
|
|
|
|
const result = await createUser(userData, AUTH_LEVELS.SUPERADMIN);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.user).toBeDefined();
|
|
expect(result.user?.name).toBe(userData.name);
|
|
expect(result.user?.username).toBe(userData.username);
|
|
expect(result.user?.email).toBe(userData.email);
|
|
});
|
|
|
|
it('should prevent admin from creating superadmin', async () => {
|
|
const userData = {
|
|
name: 'Test Superadmin',
|
|
username: 'testsuperadmin2',
|
|
email: 'testsuperadmin2@example.com',
|
|
password: 'password123',
|
|
authLevel: AUTH_LEVELS.SUPERADMIN,
|
|
status: USER_STATUS.ACTIVE,
|
|
};
|
|
|
|
const result = await createUser(userData, AUTH_LEVELS.ADMIN);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('لا يمكن للمدير إنشاء حساب مدير عام');
|
|
});
|
|
|
|
it('should prevent duplicate username', async () => {
|
|
const userData1 = {
|
|
name: 'Test User 1',
|
|
username: 'duplicatetest',
|
|
email: 'test1@example.com',
|
|
password: 'password123',
|
|
authLevel: AUTH_LEVELS.USER,
|
|
status: USER_STATUS.ACTIVE,
|
|
};
|
|
|
|
const userData2 = {
|
|
name: 'Test User 2',
|
|
username: 'duplicatetest', // Same username
|
|
email: 'test2@example.com',
|
|
password: 'password123',
|
|
authLevel: AUTH_LEVELS.USER,
|
|
status: USER_STATUS.ACTIVE,
|
|
};
|
|
|
|
await createUser(userData1, AUTH_LEVELS.SUPERADMIN);
|
|
const result = await createUser(userData2, AUTH_LEVELS.SUPERADMIN);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('اسم المستخدم موجود بالفعل');
|
|
});
|
|
});
|
|
|
|
describe('updateUser', () => {
|
|
it('should update user successfully', async () => {
|
|
const hashedPassword = await hashPassword('testpassword123');
|
|
|
|
const user = await prisma.user.create({
|
|
data: {
|
|
name: 'Original Name',
|
|
username: 'originaluser' + Date.now(),
|
|
email: 'original' + Date.now() + '@example.com',
|
|
password: hashedPassword,
|
|
authLevel: AUTH_LEVELS.USER,
|
|
status: USER_STATUS.ACTIVE,
|
|
}
|
|
});
|
|
|
|
const updateData = {
|
|
name: 'Updated Name',
|
|
email: 'updated' + Date.now() + '@example.com',
|
|
};
|
|
|
|
const result = await updateUser(user.id, updateData, AUTH_LEVELS.SUPERADMIN);
|
|
|
|
if (!result.success) {
|
|
console.log('Update failed:', result.error);
|
|
}
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.user?.name).toBe('Updated Name');
|
|
expect(result.user?.email).toBe(updateData.email);
|
|
});
|
|
});
|
|
|
|
describe('toggleUserStatus', () => {
|
|
it('should toggle user status', async () => {
|
|
const hashedPassword = await hashPassword('testpassword123');
|
|
|
|
const user = await prisma.user.create({
|
|
data: {
|
|
name: 'Test User',
|
|
username: 'teststatususer' + Date.now(),
|
|
email: 'teststatus' + Date.now() + '@example.com',
|
|
password: hashedPassword,
|
|
authLevel: AUTH_LEVELS.USER,
|
|
status: USER_STATUS.ACTIVE,
|
|
}
|
|
});
|
|
|
|
const result = await toggleUserStatus(user.id, AUTH_LEVELS.SUPERADMIN);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.user?.status).toBe(USER_STATUS.INACTIVE);
|
|
});
|
|
});
|
|
|
|
describe('deleteUser', () => {
|
|
it('should delete user successfully', async () => {
|
|
const hashedPassword = await hashPassword('testpassword123');
|
|
|
|
const user = await prisma.user.create({
|
|
data: {
|
|
name: 'Delete Test User',
|
|
username: 'deletetestuser' + Date.now(),
|
|
email: 'deletetest' + Date.now() + '@example.com',
|
|
password: hashedPassword,
|
|
authLevel: AUTH_LEVELS.USER,
|
|
status: USER_STATUS.ACTIVE,
|
|
}
|
|
});
|
|
|
|
const result = await deleteUser(user.id, AUTH_LEVELS.SUPERADMIN);
|
|
|
|
expect(result.success).toBe(true);
|
|
|
|
// Verify user is deleted
|
|
const deletedUser = await prisma.user.findUnique({
|
|
where: { id: user.id }
|
|
});
|
|
expect(deletedUser).toBeNull();
|
|
});
|
|
|
|
it('should prevent deletion of last superadmin', async () => {
|
|
// Delete any test superadmins but keep the main superadmin
|
|
await prisma.user.deleteMany({
|
|
where: {
|
|
AND: [
|
|
{ authLevel: AUTH_LEVELS.SUPERADMIN },
|
|
{ username: { not: 'superadmin' } }
|
|
]
|
|
}
|
|
});
|
|
|
|
// Try to delete the main superadmin (should fail as it's the last one)
|
|
const mainSuperadmin = await prisma.user.findUnique({
|
|
where: { username: 'superadmin' }
|
|
});
|
|
|
|
if (mainSuperadmin) {
|
|
const result = await deleteUser(mainSuperadmin.id, AUTH_LEVELS.SUPERADMIN);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('لا يمكن حذف آخر مدير عام في النظام');
|
|
} else {
|
|
// If main superadmin doesn't exist, create one and test
|
|
const hashedPassword = await hashPassword('admin123');
|
|
const superadmin = await prisma.user.create({
|
|
data: {
|
|
name: 'Last Superadmin',
|
|
username: 'lastsuperadmin' + Date.now(),
|
|
email: 'lastsuperadmin' + Date.now() + '@example.com',
|
|
password: hashedPassword,
|
|
authLevel: AUTH_LEVELS.SUPERADMIN,
|
|
status: USER_STATUS.ACTIVE,
|
|
}
|
|
});
|
|
|
|
const result = await deleteUser(superadmin.id, AUTH_LEVELS.SUPERADMIN);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('لا يمكن حذف آخر مدير عام في النظام');
|
|
}
|
|
});
|
|
});
|
|
}); |