uup
This commit is contained in:
299
app/lib/__tests__/user-management.test.ts
Normal file
299
app/lib/__tests__/user-management.test.ts
Normal file
@@ -0,0 +1,299 @@
|
||||
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('لا يمكن حذف آخر مدير عام في النظام');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user