import { describe, expect, it } from 'vitest'; import { UserRole } from '../value-objects/UserRole'; import { AdminUser } from './AdminUser'; describe('AdminUser', () => { describe('TDD - Test First', () => { it('should create a valid admin user', () => { // Arrange & Act const user = AdminUser.create({ id: 'user-123', email: 'admin@example.com', displayName: 'Admin User', roles: ['owner'], status: 'active', }); // Assert expect(user.id.value).toBe('user-123'); expect(user.email.value).toBe('admin@example.com'); expect(user.displayName).toBe('Admin User'); expect(user.roles).toHaveLength(1); expect(user.roles[0]!.value).toBe('owner'); expect(user.status.value).toBe('active'); }); it('should validate email format', () => { // Arrange & Act const user = AdminUser.create({ id: 'user-123', email: 'invalid-email', displayName: 'Test User', roles: ['user'], status: 'active', }); // Assert - Email should be created but validation happens in value object expect(user.email.value).toBe('invalid-email'); }); it('should detect system admin (owner)', () => { // Arrange const owner = AdminUser.create({ id: 'owner-1', email: 'owner@example.com', displayName: 'Owner', roles: ['owner'], status: 'active', }); const admin = AdminUser.create({ id: 'admin-1', email: 'admin@example.com', displayName: 'Admin', roles: ['admin'], status: 'active', }); const user = AdminUser.create({ id: 'user-1', email: 'user@example.com', displayName: 'User', roles: ['user'], status: 'active', }); // Assert expect(owner.isSystemAdmin()).toBe(true); expect(admin.isSystemAdmin()).toBe(true); expect(user.isSystemAdmin()).toBe(false); }); it('should handle multiple roles', () => { // Arrange & Act const user = AdminUser.create({ id: 'user-123', email: 'multi@example.com', displayName: 'Multi Role', roles: ['owner', 'admin'], status: 'active', }); // Assert expect(user.roles).toHaveLength(2); expect(user.roles.map(r => r.value)).toContain('owner'); expect(user.roles.map(r => r.value)).toContain('admin'); }); it('should handle suspended status', () => { // Arrange & Act const user = AdminUser.create({ id: 'user-123', email: 'suspended@example.com', displayName: 'Suspended User', roles: ['user'], status: 'suspended', }); // Assert expect(user.status.value).toBe('suspended'); expect(user.isActive()).toBe(false); }); it('should handle optional fields', () => { // Arrange & Act const user = AdminUser.create({ id: 'user-123', email: 'minimal@example.com', displayName: 'Minimal User', roles: ['user'], status: 'active', }); // Assert expect(user.primaryDriverId).toBeUndefined(); expect(user.lastLoginAt).toBeUndefined(); }); it('should handle all optional fields', () => { // Arrange const now = new Date(); // Act const user = AdminUser.create({ id: 'user-123', email: 'full@example.com', displayName: 'Full User', roles: ['user'], status: 'active', primaryDriverId: 'driver-456', lastLoginAt: now, }); // Assert expect(user.primaryDriverId).toBe('driver-456'); expect(user.lastLoginAt).toEqual(now); }); it('should handle createdAt and updatedAt', () => { // Arrange & Act const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['user'], status: 'active', }); // Assert expect(user.createdAt).toBeInstanceOf(Date); expect(user.updatedAt).toBeInstanceOf(Date); }); it('should handle role assignment with validation', () => { // Arrange & Act const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['user'], status: 'active', }); // Assert - Should accept any role string (validation happens in value object) expect(user.roles).toHaveLength(1); expect(user.roles[0]!.value).toBe('user'); }); it('should handle status changes', () => { // Arrange const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['user'], status: 'active', }); // Act - Use domain method to change status user.suspend(); // Assert expect(user.status.value).toBe('suspended'); }); it('should check if user is active', () => { // Arrange const activeUser = AdminUser.create({ id: 'user-123', email: 'active@example.com', displayName: 'Active User', roles: ['user'], status: 'active', }); const suspendedUser = AdminUser.create({ id: 'user-456', email: 'suspended@example.com', displayName: 'Suspended User', roles: ['user'], status: 'suspended', }); // Assert expect(activeUser.isActive()).toBe(true); expect(suspendedUser.isActive()).toBe(false); }); it('should handle role management', () => { // Arrange const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['user'], status: 'active', }); // Act user.addRole(UserRole.fromString('admin')); // Assert expect(user.roles).toHaveLength(2); expect(user.hasRole('admin')).toBe(true); }); it('should handle display name updates', () => { // Arrange const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Old Name', roles: ['user'], status: 'active', }); // Act user.updateDisplayName('New Name'); // Assert expect(user.displayName).toBe('New Name'); }); it('should handle login recording', () => { // Arrange const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['user'], status: 'active', }); const beforeLogin = user.lastLoginAt; // Act user.recordLogin(); // Assert expect(user.lastLoginAt).toBeDefined(); expect(user.lastLoginAt).not.toEqual(beforeLogin); }); it('should handle summary generation', () => { // Arrange const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['owner'], status: 'active', lastLoginAt: new Date(), }); // Act const summary = user.toSummary(); // Assert expect(summary.id).toBe('user-123'); expect(summary.email).toBe('test@example.com'); expect(summary.displayName).toBe('Test User'); expect(summary.roles).toEqual(['owner']); expect(summary.status).toBe('active'); expect(summary.isSystemAdmin).toBe(true); expect(summary.lastLoginAt).toBeDefined(); }); it('should handle equality comparison', () => { // Arrange const user1 = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['user'], status: 'active', }); const user2 = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['user'], status: 'active', }); const user3 = AdminUser.create({ id: 'user-456', email: 'other@example.com', displayName: 'Other User', roles: ['user'], status: 'active', }); // Assert expect(user1.equals(user2)).toBe(true); expect(user1.equals(user3)).toBe(false); expect(user1.equals(undefined)).toBe(false); }); it('should handle management permissions', () => { // Arrange const owner = AdminUser.create({ id: 'owner-1', email: 'owner@example.com', displayName: 'Owner', roles: ['owner'], status: 'active', }); const admin = AdminUser.create({ id: 'admin-1', email: 'admin@example.com', displayName: 'Admin', roles: ['admin'], status: 'active', }); const user = AdminUser.create({ id: 'user-1', email: 'user@example.com', displayName: 'User', roles: ['user'], status: 'active', }); // Assert - Owner can manage everyone expect(owner.canManage(admin)).toBe(true); expect(owner.canManage(user)).toBe(true); expect(owner.canManage(owner)).toBe(true); // Can manage self // Admin can manage users but not admins/owners expect(admin.canManage(user)).toBe(true); expect(admin.canManage(admin)).toBe(false); expect(admin.canManage(owner)).toBe(false); // User cannot manage anyone except self expect(user.canManage(user)).toBe(true); expect(user.canManage(admin)).toBe(false); expect(user.canManage(owner)).toBe(false); }); it('should handle role modification permissions', () => { // Arrange const owner = AdminUser.create({ id: 'owner-1', email: 'owner@example.com', displayName: 'Owner', roles: ['owner'], status: 'active', }); const admin = AdminUser.create({ id: 'admin-1', email: 'admin@example.com', displayName: 'Admin', roles: ['admin'], status: 'active', }); const user = AdminUser.create({ id: 'user-1', email: 'user@example.com', displayName: 'User', roles: ['user'], status: 'active', }); // Assert - Only owner can modify roles expect(owner.canModifyRoles(user)).toBe(true); expect(owner.canModifyRoles(admin)).toBe(true); expect(owner.canModifyRoles(owner)).toBe(false); // Cannot modify own roles expect(admin.canModifyRoles(user)).toBe(false); expect(user.canModifyRoles(user)).toBe(false); }); it('should handle status change permissions', () => { // Arrange const owner = AdminUser.create({ id: 'owner-1', email: 'owner@example.com', displayName: 'Owner', roles: ['owner'], status: 'active', }); const admin = AdminUser.create({ id: 'admin-1', email: 'admin@example.com', displayName: 'Admin', roles: ['admin'], status: 'active', }); const user = AdminUser.create({ id: 'user-1', email: 'user@example.com', displayName: 'User', roles: ['user'], status: 'active', }); // Assert - Owner can change anyone's status expect(owner.canChangeStatus(user)).toBe(true); expect(owner.canChangeStatus(admin)).toBe(true); expect(owner.canChangeStatus(owner)).toBe(false); // Cannot change own status // Admin can change user status but not admin/owner expect(admin.canChangeStatus(user)).toBe(true); expect(admin.canChangeStatus(admin)).toBe(false); expect(admin.canChangeStatus(owner)).toBe(false); // User cannot change status expect(user.canChangeStatus(user)).toBe(false); expect(user.canChangeStatus(admin)).toBe(false); expect(user.canChangeStatus(owner)).toBe(false); }); it('should handle deletion permissions', () => { // Arrange const owner = AdminUser.create({ id: 'owner-1', email: 'owner@example.com', displayName: 'Owner', roles: ['owner'], status: 'active', }); const admin = AdminUser.create({ id: 'admin-1', email: 'admin@example.com', displayName: 'Admin', roles: ['admin'], status: 'active', }); const user = AdminUser.create({ id: 'user-1', email: 'user@example.com', displayName: 'User', roles: ['user'], status: 'active', }); // Assert - Owner can delete anyone except self expect(owner.canDelete(user)).toBe(true); expect(owner.canDelete(admin)).toBe(true); expect(owner.canDelete(owner)).toBe(false); // Cannot delete self // Admin can delete users but not admins/owners expect(admin.canDelete(user)).toBe(true); expect(admin.canDelete(admin)).toBe(false); expect(admin.canDelete(owner)).toBe(false); // User cannot delete anyone expect(user.canDelete(user)).toBe(false); expect(user.canDelete(admin)).toBe(false); expect(user.canDelete(owner)).toBe(false); }); it('should handle authority comparison', () => { // Arrange const owner = AdminUser.create({ id: 'owner-1', email: 'owner@example.com', displayName: 'Owner', roles: ['owner'], status: 'active', }); const admin = AdminUser.create({ id: 'admin-1', email: 'admin@example.com', displayName: 'Admin', roles: ['admin'], status: 'active', }); const user = AdminUser.create({ id: 'user-1', email: 'user@example.com', displayName: 'User', roles: ['user'], status: 'active', }); // Assert expect(owner.hasHigherAuthorityThan(admin)).toBe(true); expect(owner.hasHigherAuthorityThan(user)).toBe(true); expect(admin.hasHigherAuthorityThan(user)).toBe(true); expect(admin.hasHigherAuthorityThan(owner)).toBe(false); expect(user.hasHigherAuthorityThan(admin)).toBe(false); }); it('should handle role display names', () => { // Arrange const user = AdminUser.create({ id: 'user-123', email: 'test@example.com', displayName: 'Test User', roles: ['owner', 'admin'], status: 'active', }); // Act const displayNames = user.getRoleDisplayNames(); // Assert expect(displayNames).toContain('Owner'); expect(displayNames).toContain('Admin'); }); }); });