Files
gridpilot.gg/core/admin/domain/entities/AdminUser.test.ts
2026-01-01 12:10:35 +01:00

531 lines
14 KiB
TypeScript

import { AdminUser } from './AdminUser';
import { UserRole } from '../value-objects/UserRole';
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');
});
});
});